我正在为marked实现自定义渲染功能,该功能将检查图像上的一些条件,执行异步请求,然后从其他来源返回图像。但是,由于新请求是异步的,因此我只会得到一个诺言,而不是一个“真实的”图像网址。
attachmentService.getBlobUrl
是一个异步函数,它执行http请求并返回一个Promise。
我的渲染函数如下:
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}"/>`
},
}
})
我已经尝试过直接返回图片标签:
// ...
return this.attachmentService.getBlobUrl(attachment)
.then(url => {
return `<img src="${url}" alt="${text}" title="${title}"/>`
})
// ...
我也尝试过将函数包装在async
调用中并返回(不包装在Promise.resolve
中):
// ...
return (async () => {
return await this.attachmentService.getBlobUrl(attachment)
.then(url => {
return `<img src="${url}" alt="${text}" title="${title}"/>`
})
})()
// ...
但是,这也只能给我一个诺言。
我不能使用await
,因为渲染功能本身必须是同步的-这不是我可以控制的。
答案 0 :(得分:1)
您可以推迟异步操作:
class
名称,就应该区别对待。您还可以将src
属性更改为某些加载图片。MutationObserver
并仅侦听添加的那些元素。然后,在MutationObserver的回调中,您可以执行异步操作并更新元素的src
。答案 1 :(得分:0)
render函数本身必须是同步的
然后就不能在其中使用像ERROR: multiple drivers on net 'LED' (LED_SB_DFFNE_Q.Q and LED_SB_DFFNE_Q_1.Q)
这样的异步函数。您永远无法完成这项工作,这是完全不可能的。
相反,您将需要重新设计您的方法。评估条件并在调用getBlobUrl
之前 进行异步请求。然后传递可以同步呈现的数据。
答案 2 :(得分:0)
我最终向需要特殊处理的class
元素添加了一个新的img
,并在将markdown编译为html之后遍历了它们:
marked.use({
renderer: {
image: (src, title, text) => {
title = title ? ` title="${title}` : ''
if (someCondition) {
return `<img data-src="${src}" alt="${text}" ${title} class="attachment-image"/>`
}
return `<img src="${src}" alt="${text}" ${title}/>`
},
}
})
this.preview = DOMPurify.sanitize(marked(this.text))
// Since the render function is synchronous, we can't do async http requests in it.
// Therefore, we can't resolve the blob url at (markdown) compile time.
// To work around this, we modify the url after rendering it in the vue component.
// We're doing the whole thing in the next tick to ensure the image elements are
// available in the dom tree. If we're calling this right after setting this.preview
// it could be the images were already made available.
this.$nextTick(() => {
document.getElementsByClassName('attachment-image').forEach(img => {
// ...
// some code ...
// ...
this.attachmentService.getBlobUrl(attachment)
.then(url => {
img.src = url
})
})
})
这是在vue js组件内发生的,该组件将this.preview
转换为v-html
到元素。
需要在this.$nextTick
中进行调用,以确保img
元素可用,以便对其进行修改。
此解决方案类似于@shilch提出的解决方案,但我想应该是“ vue-y”。