promise.all 是如何工作的?

How does promise.all work?

我开始挖掘承诺并发现有趣 Promise.all。

在 MDN 中声明

The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved.

这基本上意味着设置承诺在参数列表中的所有承诺都已解决之后解决。我试图实现它。我只是答应 ajax 打电话。

var get = function(url) {
    return new Promise(function(resolve,reject) {
        var xhtml=new XMLHttpRequest();

        xhtml.open("GET",url);
        xhtml.responseType = 'blob';
        xhtml.onload = function() {
            if(xhtml.status==200){
                resolve(xhtml.response);
            } else {
                reject(Error("Error"+statusText));
            }
        }
        xhtml.send();
    });

}

get("one.jpg").then(function(response){
    var blob = window.URL.createObjectURL(response);
    var img = document.createElement("img");

    console.log("Success"+response);

    img.src = blob;

    document.body.appendChild(img);
});

效果很好。但是在我尝试添加 Promise.all 之后它抛出了一个错误。

Promise.all(get).then(function(response){alert("done")});

正如我所说,这引发了错误“Promise.all 的参数 1 无法转换为序列。” 所以我假设我没有理解 promise.all 的含义。 它是如何工作的?

你的get函数returns一个Promise。您只是传递对 get 函数的引用。您必须传递 Promises

的数组
Promise.all([get("one.jpg")]).then(...);

Promise.all 获取一组(或任何可迭代的)承诺,并在所有承诺都履行时履行或在其中一个拒绝时拒绝。我认为如果我们实现它并理解我们为什么需要它,它会更容易理解。

一个常见的用例可能是等待 window 加载并等待服务器 return 数据以便 运行 一些代码:

// a function that returns a promise for when the document is ready.
function windowReady(){
    return new Promise(function(resolve){
         window.addEventListener('DOMContentLoaded', resolve);
    }); 
}

// function that returns a promise for some data
function getData(){
    return fetch("/").then(function(r){ return r.json() });
}

现在,我们想让它们同时执行,然后得到结果。这里有两个项目,但很容易有 5 个要等待的东西,或者 100 个。所以我们使用 Promise.all:

Promise.all([windowReady(), getData()]).then(function(results){
     // results[1] is the data, it's all in an array.
});

让我们看看如何实现它:

function all(iterable){ // take an iterable 
  // `all` returns a promise.  
  return new Promise(function(resolve, reject){ 
    let counter = 0; // start with 0 things to wait for
    let results = [], i = 0;
    for(let p of iterable){
        let current = i;
        counter++; // increase the counter 
        Promise.resolve(p).then(function(res){ // treat p as a promise, when it is ready: 
          results[i] = res; // keep the current result
          if(counter === 0) resolve(results) // we're done
        }, reject); // we reject on ANY error
       i++; // progress counter for results array
    }
  });
}

或者,在更多的 ES6 中:

let all = iterable => new Promise((resolve, reject) => { 
  let arr = [...iterable], c = arr.length, results = [];
  arr.map(Promise.resolve, Promise).
      map((p, i) => p.then(v => { 
        r[i] = v;
        if(--c === 0) resolve(r);
      } , reject));
});

TLDR:

Promise.all 是一个 Javascript 方法,它将承诺的可迭代(例如 Array)作为参数,并且 returns 当 时接受单个承诺all 可迭代参数中的承诺已被解决(或者当可迭代参数不包含任何承诺时)。它使用已解析值的数组进行解析,并使用第一个被拒绝的 Promise 的单个值进行拒绝。

示例:

var promise1 = Promise.resolve(5);
var promise2 = Math.random() > 0.5? 1 : Promise.reject(1); // either resolves or rejects
var promise3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('foo'), 1000);
});

Promise.all([promise1, promise2, promise3]).then((val) => {
  console.log(val);
}).catch((val) => {
  console.log(val);
});

在上面的示例中,3 个 Promise 作为数组传递给 Promise.all 函数。承诺 1 和 3 始终解决。 Promise 2 根据随机 Nr 生成器解决或拒绝。这个 Promise.all 方法然后 returns 一个基于随机 Nr 生成器的已解决或拒绝的 Promise。

然后 then() 方法和 catch() 方法可以在这个从 Promise.all 返回的承诺上调用。 then() 方法获取所有已解析值的数组,在本例中为 [5, 1, 'foo']catch() 方法获取第一个被拒绝的 Promise 的值,在本例中为 1

何时使用:

当您想执行多个 异步操作并且需要在异步操作后处理结果时,此方法非常有用。使用 Promise.all 时,可以同时处理所有承诺,同时仍然可以对所有传入数据进行操作。

例如,当我们需要使用多个 AJAX 请求获取信息并将数据组合成有用的东西时。必须等待所有数据可用,否则我们会尝试合并不存在的数据,这会导致问题。

Promise.all(iterables) 函数 returns 单个 Promise.Here 我们提供多个 Promise 作为参数。 Promise.all(iterables) 函数 returns 仅当所有承诺(参数)都已解决时才承诺。 当第一个承诺参数拒绝时它拒绝。

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
// expected output: Array [3, 42, "foo"]
});

语法:

Promise.all(func1, func2 [funcN])

参数:

阅读更多信息 - https://www.oodlestechnologies.com/blogs/An-Introduction-To-Promise.all-Function

免责声明:我为 oodles technologies 工作