promise.all如何运作?

Dar*_*lyn 6 javascript promise es6-promise

我在承诺中开始挖掘,发现了有趣的Promise.all.

在MDN中说明了这一点

Promise.all(iterable)方法返回一个promise,该promise在迭代参数中的所有promise都已解析时解析.

这基本上意味着设置promises会在之后解析并且如果参数列表中的所有promise都已解决.我试图实现它.我做了简单的承诺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);
});
Run Code Online (Sandbox Code Playgroud)

哪个工作正常.但在我尝试添加Promise.all之后,它抛出了一个错误.

Promise.all(get).then(function(response){alert("done")});
Run Code Online (Sandbox Code Playgroud)

这就像我说的那样抛出一个错误"Promise.all的参数1无法转换为序列." 所以我假设我没有得到promise.all的含义.它是如何工作的?

Ben*_*aum 5

Promise.all采用一个数组(或任何可迭代的)承诺,当其中一个承诺完成或拒绝时,其中一个承诺拒绝.我认为,如果我们实施它并理解为什么需要它,就会更容易理解.

一个常见的用例可能是等待窗口加载,服务器返回数据以运行一些代码:

// 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() });
}
Run Code Online (Sandbox Code Playgroud)

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

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

让我们看看我们如何实现它:

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;
    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
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

或者,更多ES6ness:

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));
});
Run Code Online (Sandbox Code Playgroud)