ES6 Promise.all进展

Aug*_*ger 17 javascript es6-promise

在进一步讨论之前,我需要解决几项承诺.

Promise.all(promises).then((results) => {
  // going further
}); 
Run Code Online (Sandbox Code Playgroud)

我有什么办法可以取得Promise.all承诺的进展吗?

从文档来看,它似乎是不可能的.而这个问题并没有任何回答.

所以:

  • 你不同意这会有用吗?我们不应该查询此功能吗?
  • 现在如何手动实现它?

Kei*_*ith 28

我已经敲了一个你可以重复使用的辅助功能.

基本上按照惯例传递你的承诺,并提供一个回调来做你想要的进展..

function allProgress(proms, progress_cb) {
  let d = 0;
  progress_cb(0);
  for (const p of proms) {
    p.then(()=> {    
      d ++;
      progress_cb( (d * 100) / proms.length );
    });
  }
  return Promise.all(proms);
}

function test(ms) {
  return new Promise((resolve) => {
    setTimeout(() => {
       console.log(`Waited ${ms}`);
       resolve();
     }, ms);
  });
}


allProgress([test(1000), test(3000), test(2000), test(3500)],
  (p) => {
     console.log(`% Done = ${p.toFixed(2)}`);
});
Run Code Online (Sandbox Code Playgroud)


nao*_*tor 5

您可以在每个承诺中添加.then()来计算谁的完成。就像是 :

var count = 0;

var p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, 'boo');
}); 
var p2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 7000, 'yoo');
}); 
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'foo');
}); 

var promiseArray = [
  p1.then(function(val) {
    progress(++count); 
    return val 
  }), 
  p2.then(function(val) {
    progress(++count); 
    return val 
  }), 
  p3.then(function(val) {
    progress(++count); 
    return val 
  })
]

function progress(count) {
  console.log(count / promiseArray.length);
}

Promise.all(promiseArray).then(values => { 
  console.log(values);
});
Run Code Online (Sandbox Code Playgroud)


Pat*_*rts 5

这比基思的答案有一些优点:

  • 回调onprogress()永远不会同步调用。这确保回调可以依赖于调用后同步运行的代码Promise.progress(...)
  • Promise 链将进程事件中抛出的错误传播给调用者,而不是允许未捕获的 Promise 拒绝。这确保了通过强大的错误处理,调用者能够防止应用程序进入未知状态或崩溃。
  • 回调收到的是一个ProgressEvent而不是百分比。0 / 0这通过避免商来减轻处理进度事件的难度NaN
Promise.progress = async function progress (iterable, onprogress) {
  // consume iterable synchronously and convert to array of promises
  const promises = Array.from(iterable).map(this.resolve, this);
  let resolved = 0;

  // helper function for emitting progress events
  const progress = increment => this.resolve(
    onprogress(
      new ProgressEvent('progress', {
        total: promises.length,
        loaded: resolved += increment
      })
    )
  );

  // lift all progress events off the stack
  await this.resolve();
  // emit 0 progress event
  await progress(0);

  // emit a progress event each time a promise resolves
  return this.all(
    promises.map(
      promise => promise.finally(
        () => progress(1)
      ) 
    })
  );
};
Run Code Online (Sandbox Code Playgroud)

请注意,ProgressEvent支持有限。如果此覆盖范围不能满足您的要求,您可以轻松地填充以下内容:

class ProgressEvent extends Event {
  constructor (type, { loaded = 0, total = 0, lengthComputable = (total > 0) } = {}) {
    super(type);
    this.lengthComputable = lengthComputable;
    this.loaded = loaded;
    this.total = total;
  }
}
Run Code Online (Sandbox Code Playgroud)