promiseを実現するallメソッド

2170 ワード

Promise.all()は、配列がパラメータであることを受信し、配列のすべてのPromiseがresolveの状態である場合、Promise.all()こそ成功する.失敗が一つあれば、失敗と見なされます.次の例を簡単に見てみましょう
var p1 = Promise.resolve('a');
 var p2 = Promise.resolve('b');
 var p3 = Promise.resolve('c');
Promise.all([p1,p2,p3]).then(value => {
    console.log(value);
})

疑う必要はありません.上のコードの実行結果はa,b,cです.p 1,p 2,p 3はいずれも成功した状態であるからである.次の例を見てみましょう
var p1 = new Promise((resolve, reject) => {
    resolve('hello');
})
.then(result => result)
.catch(e => e);

var p2 = new Promise((resolve, reject) => {
    throw new Error('   ');
})
.then(result => result)
.catch(e => e);

Promise.all([p1,p2])
.then(value => {
    console.log(value);
})
.catch(err => {
    console.log(err);
})

この時皆さんの最初の考えはこのallが失敗するのではないでしょうか.ええ、実は私も最初はそう思っていましたが、このコードをよく分析すると、私たちが思っているほど簡単ではありません.次に分析します.
  • p 1は間違いなく成功したに違いない.
  • p 2は関数に直接エラーを投げ出した.しかし、p 2には独自のcatchの関数があり、catch関数は前に投げ出されたエラーをキャプチャすることができることに注意してください.
  • p 2自体がエラーをキャプチャできるのでPromise.all()メソッドではp 1,p 2の両方のPromiseがresolveの状態であるためthenメソッドで指定されたコールバック関数が呼び出される.

  • 最後に実装を見てみましょうall()メソッドのプロセス.ここでは,この方法で受信したパラメータが配列でありpromiseオブジェクトを返すことを明確にしなければならない.
    //       promise
    function isPromise(value){
        if(typeof value === 'function' || (typeof value === 'undefined' && value != null)){
            if(typeof value.then === 'function'){
                return true;
            }
        }
        return false;
    }
    
    Promise.all = function(values){
        return new Promise((resolve,reject)=>{
            let arr = [];
            let i = 0;
            let processData = function(key,value){
                arr[key] = value;
                if(++i === values.length){
                    resolve(arr)
                }
            }
            for(let i = 0; i < values.length; i++){
                let current = values[i];
                if(isPromise(current)){   //       promise      
                    current.then(y=>{
                        processData(i,y)
                    },reject)
                }else{
                    processData(i,current)
                }
            }
        })
    }