使用dom-to-image library我们可以使用Promises转换图像。
用法示例,从DOM对象转换为PNG图像:
var node = document.getElementById('my-node');
domtoimage.toPng(node)
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
在幕后,toPng方法是Promise对象的链:
/**
* @param {Node} node - The DOM Node object to render
* @param {Object} options - Rendering options, @see {@link toSvg}
* @return {Promise} - A promise that is fulfilled with a PNG image data URL
* */
function toPng(node, options) {
return draw(node, options || {})
.then(function (canvas) {
return canvas.toDataURL();
});
}
我想基于Node数组转换图像,然后按顺序获取图像。问题是当我调用toPng()
时,异步处理时间随DOM目标复杂度的变化而变化。因此它将在复杂性较低的页面之前返回,而不是按顺序返回页面。
let pages = document.querySelectorAll('.page');
pages.forEach(page => {
let dataUrl = convertToPng(page.firstElementChild);
});
function convertToPng(page) {
domtoimage.toPng(page)
.then(function (dataUrl) {
console.log(page); // prints pages randomly (e.g. page3, page1, page2)
})
}
一种可能的解决方案是使用Promise.all()
方法并使用forEach()
方法附加所有Promises。但在这种情况下,我使用的是外部库,我不知道如何获取第一页,然后是页面2,依此类推...
答案 0 :(得分:3)
使用async
/ await
:
HTML:
<div class="page">Hello 1</div>
<div class="page">Hello 2</div>
<div class="page">Hello 3</div>
<div class="page">Hello 4</div>
JS(JSFiddle Link):
let pages = document.querySelectorAll('.page');
async function getPageUrls() {
for (let page of pages) {
const url = await convertToPng(page);
console.log(url);
}
}
async function convertToPng(page) {
return await domtoimage.toPng(page);
}
getPageUrls();
基于OPs样本(JSFiddle):
let pages = document.querySelectorAll('.page');
for (let page of pages) {
convertToPng(page);
}
async function convertToPng(page) {
const dataUrl = await domtoimage.toPng(page);
console.log(dataUrl);
}
getPageUrls();
使用此解决方案,代码执行将停止,直到convertToPng
在每次迭代时产生结果。
答案 1 :(得分:2)
据我所知,您可以使用Promise.all
。像这样的人:
let pages = document.querySelectorAll('.page');
Promise.all(Array.prototype.slice.call(pages,0)
.map(page =>domtoimage.toPng(page)
).then((pages)=>{.... your handler....});
有关Promise.all的更多信息,您可以从MDN
获取答案 2 :(得分:2)
将promises链接起来以便顺序运行的最简单方法是使用Array#reduce
pages.reduce((promise, page) =>
promise.then(() => convertToPng(page.firstElementChild)),
Promise.resolve() // this starts the chain
);
正如您在评论wait until page1 is complete, before beginning with the next page
虽然,我觉得它只是输出顺序很重要,在这种情况下@VasylMoskalov的答案更合适
正如@Keith在评论中指出的那样 - convertToPng不会返回任何内容(更不用说承诺了)
function convertToPng(page) {
//vvvvvv important you return the promise here
return domtoimage.toPng(page)
.then(function (dataUrl) {
console.log(page); // prints pages randomly (e.g. page3, page1, page2)
})
}