I am implementing a custom render function for marked which will check a few conditions on images, does an async request and then returns an image from a different source. However, since the new request is asynchronous, I will only ever get a promise back instead of a "real" image url.
attachmentService.getBlobUrl
is an async function which does an http request and returns a promise.
My render function looks like this:
marked.use({
renderer: {
image: (src, title, text) => {
if (someCondition) {
// Some code of parsing the src attribute
// ...
return this.attachmentService.getBlobUrl(attachment)
.then(url => {
return Promise.resolve(`<img src="${url}" alt="${text}" title="${title}"/>`)
})
}
return `<img src="${src}" alt="${text}" title="${title}"/>`
},
}
})
I already tried returning the image tag directly:
// ...
return this.attachmentService.getBlobUrl(attachment)
.then(url => {
return `<img src="${url}" alt="${text}" title="${title}"/>`
})
// ...
I have also tried wrapping the function in an async
call and returning that (not wrapped in a Promise.resolve
):
// ...
return (async () => {
return await this.attachmentService.getBlobUrl(attachment)
.then(url => {
return `<img src="${url}" alt="${text}" title="${title}"/>`
})
})()
// ...
However, this also only gives me a promise.
I cannot use await
because the render function itself must be synchronous - that's not something I have control over.
You can defer your asynchronous operation:
class
name to the img elements that should be treated differently. You could also change thesrc
attribute to some loading image.MutationObserver
and only listen for those elements getting added. In the MutationObserver's callback you can then perform your asynchronous operation and update the element'ssrc
.