11

私は Promise を掘り下げ始め、興味深い Promise.all を見つけました。

MDN には次のように記載されています。

Promise.all(iterable) メソッドは、 iterable 引数のすべての promise が解決されたときに解決される 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);
});

これはうまくいきます。しかし、Promise.all を追加しようとすると、エラーがスローされました。

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

私が言ったように、これは「Promise.allの引数1はシーケンスに変換できません」というエラーをスローしました。だから私はpromise.allの意味を理解していないと思います。それはどのように機能しますか?

4

4 に答える 4

8

Promise.allPromise の配列 (または任意のイテラブル) を取り、それらすべてが満たされている場合は満たし、そのうちの 1 つが拒否されている場合は拒否します。それを実装して、なぜそれが必要なのかを理解すれば、理解しやすいと思います。

一般的な使用例は、ウィンドウがロードされ、サーバーがコードを実行するためにデータを返すのを待つことです。

// 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() });
}

ここで、両方を同時に実行して結果を取得します。ここには 2 つの項目がありますが、待つべき項目が 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
    }
  });
}

または、さらに 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));
});
于 2015-07-08T17:26:59.280 に答える
4

関数getは を返しますPromiseget関数への参照を渡すだけです。の配列を渡す必要がありますPromises

Promise.all([get("one.jpg")]).then(...);
于 2015-07-08T17:13:03.967 に答える