Javascript 使用库dom对图像按顺序返回承诺结果

Javascript 使用库dom对图像按顺序返回承诺结果,javascript,promise,Javascript,Promise,使用,我们可以使用承诺转换图像 使用示例,从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); }) .

使用,我们可以使用承诺转换图像

使用示例,从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();
        });
}
我想基于节点数组转换图像,然后按顺序获得图像。问题是当我调用
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()
方法附加所有承诺。但在这种情况下,我使用的是一个外部库,我不知道如何先获取页面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的更多信息,您可以从

中获得,据我所知,在本例中,您可以使用
Promise.all
。像这样的事情:

let pages = document.querySelectorAll('.page');

Promise.all(Array.prototype.slice.call(pages,0)
.map(page =>domtoimage.toPng(page)
).then((pages)=>{.... your handler....});

有关承诺的更多信息。您可以从

获得的所有信息链接承诺以便它们按顺序运行的最简单方法是使用数组#reduce

正如您在注释
中所述,这将等待第1页完成,然后再开始下一页

不过,我觉得只有输出顺序才是重要的,在这种情况下,@VasylMoskalov的答案更合适

正如@Keith在一篇评论中指出的那样,convertToPng不会返回任何东西(更不用说承诺了)


链接承诺以使其按顺序运行的最简单方法是使用Array#reduce

正如您在注释
中所述,这将等待第1页完成,然后再开始下一页

不过,我觉得只有输出顺序才是重要的,在这种情况下,@VasylMoskalov的答案更合适

正如@Keith在一篇评论中指出的那样,convertToPng不会返回任何东西(更不用说承诺了)


使用
异步
/
等待

HTML:

基于OPs示例():


使用此解决方案,代码执行将停止,直到每次迭代时
convertToPng
产生结果。

使用
async
/
wait

HTML:

基于OPs示例():



使用此解决方案,代码执行将停止,直到每次迭代时
convertToPng
生成一个结果。

是否链接承诺?我想你想等到第1页“完成”后再开始第2页,等等?@JaromandaX是的,我想等到第1页完成后再开始下一页。如果你想真正时髦,试着使用
async/await
@Keith I know
async/await
,但我不知道如何在这个库中应用它。ps。。还要确保您从
convertToPng
返回您的承诺……是否可以将承诺链接起来?我想你想等到第1页“完成”后再开始第2页,等等?@JaromandaX是的,我想等到第1页完成后再开始下一页。如果你想真正时髦,试着使用
async/await
@Keith I know
async/await
,但我不知道如何在这个库中应用它。ps。。另外,请确保您从
convertToPng
…返回您的承诺,因为OP显然使用了现代JS-为什么不
promise.all(Array.from(pages,page=>domtoimage.toPng(page))。然后(pages=>{…})
:p可能我有点正统:)谢谢您的回复,但是我不明白为什么要使用
array.slice
array.from
if
querySelectorAll
返回数组对象@雅罗曼德斯。编辑:好的,这是一个
节点列表
,我一直认为它与数组相同,但它只继承
forEach
方法。它不返回数组。。这是一个
节点列表
。。。具有有限的类似数组的功能(即,它有一个
长度
属性,在一些现代浏览器中有一个
.forEach
.keys
.values
.entries
方法…但没有
.map
方法-这对呈现的代码的工作至关重要)既然OP显然在使用现代JS,为什么不
Promise.all(Array.from(pages,page=>domtoimage.toPng(page))。然后(pages=>{…})
:p可能我有点正统:)谢谢你的回复,但是我不明白为什么要使用
array.slice
array.from
if
querySelectorAll
返回数组对象@雅罗曼德斯。编辑:好的,这是一个
节点列表
,我一直认为它与数组相同,但它只继承
forEach
方法。它不返回数组。。这是一个
节点列表
。。。具有有限的类似数组的功能(即,它有一个
长度
属性,在一些现代浏览器中有一个
.forEach
.keys
.values
.entries
方法…但没有
.map
方法-这对呈现的代码的工作至关重要)你能更详细地解释一下阵列的作用吗?我理解这一点,但我不知道为什么以及它是如何工作的。据我所知,谢谢你承诺。所有保留订单这将创建一个承诺链。。。但是我没有展示一件事,所以这可能会澄清它up@VasylMoskalov-是的,由Promise.all解析的数组保留了输入数组到Promise.all的顺序-我认为您的答案可能更合适,因为异步操作是“尽可能快地”完成的,就像这段代码一样,它是按照OP所说的一次完成一个,你的是正确的..-><代码>是,我想等到第1页完成后,
您能更详细地解释一下阵列的作用吗?我理解这一点,但我不知道为什么以及它是如何工作的。据我所知,谢谢你承诺。所有保留订单这将创建一个承诺链。。。我一点也没表现出来
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) 
    })
}
<div class="page">Hello 1</div>
<div class="page">Hello 2</div>
<div class="page">Hello 3</div>
<div class="page">Hello 4</div>
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();
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();