按顺序生成 运行 的承诺数组

Generate an array of promises to run sequentially

我正在尝试按顺序为 运行 生成一组 Promise。我已经看到很多关于此的提示,但在我的用例中无法达到 运行。

export default function generateIcons(){
  return new Promise((resolve, reject) => {
    const containers = document.querySelectorAll('.html2CanvasTarget')
    const promises = containers.map(child => processIcon(child))
    promises.reduce((p, fn) => p.then(fn), Promise.resolve())
    resolve()
  })
}

function processIcon(child){
  return new Promise((resolve, reject) => html2canvas(child).
 then(canvas => uploadFromCanvas(canvas,
  child.childNodes[0].className.split(' ')[1] + '.png'))
 .then(resolve).catch(reject))
}

有什么建议吗?这只是拒绝,我不明白为什么

containers 是一个 NodeList,而 NodeList 没有 .map 方法,这就是您的代码抛出错误的原因。

因为 processIcon 已经 return 是一个 Promise,所以没有必要再次使用 Promise 构造函数 html2canvas 已经 return 也是一个 Promise,因此任何地方都不需要任何 Promise 构造函数(参见 What is the explicit promise construction antipattern and how do I avoid it?

如果可能,在 for 循环中每次调用 await。因为 uploadFromCanvas return 也是一个 Promise,而您想等待它,return 它(或 await 它)也是如此:

export default async function generateIcons() {
  const containers = document.querySelectorAll('.html2CanvasTarget');
  for (const container of containers) {
    await processIcon(container);
  }
}

function processIcon(child) {
  return html2canvas(child, {backgroundColor:null})
    .then(canvas => uploadFromCanvas(canvas, child.className.split(' ')[1] + '.png'))
    .catch(console.log);        
}

根据你的问题,你可以使用 Q module 模块

你需要一个空数组并将promises推入其中,并在Q方法中传递这个数组(Q.allSettled),看一个例子

const Q = require('q');

const promiseHolder = [];

for (let i = 0; i < 10; i += 1) {
  promiseHolder.push('Your Promises');
}

Q.allSettled(promises)
  .then((results) => {
    results.forEach((result) => {
      if (result.state === 'fulfilled') {
        const value = result.value;
        return value;
      } 
        const reason = result.reason;
        throw reason;      
    });
  });

Q.allSettled()中的方法总是在.then()中得到结果。有2个州。一个成功,一个失败。

成功 => 状态 === 'fulfilled', : 'Whatever your promise return'

失败 => 状态 === 'rejected', 原因: 'Whatever your promise thrown'

在这种情况下,您有许多成功和不成功的承诺。

第二种方法是 Promise.all() 做同样的事情,但问题是每当任何承诺被拒绝进一步的承诺从未被调用。

const promiseHolder = [];

for (let i = 0; i < 10; i += 1) {
  promiseHolder.push('Your Promises');
}

Promise.all(promiseHolder)
  .then((results) => {
    return results;
  })
  .catch((err) => {
    throw err;
  });

在第二种方法 (Promise.all()) 中,它包含从 for loop 推送的所有承诺。如果任何一个 promise rejected 没有更多的 promise 调用,突然你在 Promise.all() 中得到了 promise rejection 的状态。

Promise.all(promiseHolder)
  .then((results) => {
    return results;
  })
  .catch((err) => {
    console.log('Promise will reject here', err);
    throw err;
  });

希望对您有所帮助,编码愉快:)

您似乎想在画布可用于所有子元素时解决主要承诺。您可以为此使用 Promise.All()

还应注意 querySelectorAll 不会 return 任何您可以调用 .map 的东西。您将必须从 querySelectorAll return 中创建一个数组 - 这是一个 NodeList

export default function generateIcons(){
  return new Promise((resolve, reject) => {

    const containers = document.querySelectorAll('.html2CanvasTarget');
    const promises = Array.from(containers).map(child => processIcon(child))

    Promises.All(promises).then(() => resolve());
  })
}