2016-12-25 4 views
8

非同期関数のすべての結果を返す関数を記述し、配列にプッシュしてすべての非同期関数の結果を記録するコールバックを実行しようとします。JS:非同期関数で内部関数の引数を取得し、コールバックを実行

すべての料理が終わるとすべての料理を持ってくるウェイター。 結果として返される子の引数を取得する方法を理解できません。タスクと私の働いていないソリューションのコードは以下の通りです:

タスク:

var dishOne = function(child) { 
    setTimeout(function() { 
     child('soup'); 
    }, 1000); 
}; 

var dishTwo = function(child) { 
    setTimeout(function() { 
     child('dessert'); 
    }, 1500); 
}; 
waiter([dishOne, dishTwo], function(results) { 
    console.log(results); // console output = ['soup', 'dessert'] 
}); 

私の働いていない解決策:

funcArray.forEach(function(f) { 
    f(x) 
    i++; 
    if(i == 2) { 
    doneAll(result.arr) 
    } 
}); 

function child(arg) { 
    this.arr.push(arg) 
} 

function waiter(funcArray, doneAll) { 
    var result = { 
     arr: [] 
    }; 
    let i = 0; 
    const x = child.bind(result) 
    funcArray.forEach(function(f) { 
     f(x) 
     i++; 
     if(i == 2) { 
     doneAll(result.arr) 
     } 
    }); 
} 

答えて

5

問題は、この部分ですこれは同期関数なので、if(i == 2)をチェックすると、基本的にすべてのまだ何も返されていないので、関数は呼び出されていますが、result.arrはまだ設定されていません。

doneAll(result.arr)式をchildコールバックに移動する必要があります。結果を返すときに非同期関数によって呼び出されます。

私は結果オブジェクト

var result = { 
    arr: [] 
    , allCount: funcArray.length 
    , doneAll: doneAll 
}; 

これは働くものと強化

function child(arg) { 
    if (this.arr.push(arg) === this.allCount) this.doneAll(this.arr); 
} 

とあなたのwaiter機能のように、あなたのchildを書いているのだと思いますが、一つの欠点を持っていることができます最も単純ソリューション - 結果の位置funcArrayの関数の位置を保持していない場合、結果の位置は非同期関数の長さでソートされます。単純に最初の解決結果は最初の結果などです。これが問題であれば、index child関数を結果配列の貴重な位置に結果を格納し、arr.lengthによるチェックは機能しません。なぜなら、JS配列は長さが最高のインデックス+ 1として返されるからです。最後のfuncArrayが最後に満たされると、 result.arrの長さはthis.allCountと等しくなるので、結果の順序をfuncArrayと同じに保つには、返された結果の数を別の数として保存し、新しい結果ごとにその数を増やして、その数をallCountと比較する必要があります。

またはSO

function child(idx, arg) { 
    this.arr[idx] = arg; 
    if (--this.allCount === 0) this.doneAll(this.arr); 
} 

ようallCountを減少させ、あなたのwaiter機能

function waiter(funcArray, doneAll) { 
    const result = { 
     arr: [] 
     , allCount: funcArray.length 
     , doneAll: doneAll 
    }; 

    funcArray.forEach(function(f, i) { 
     f(child.bind(result, i)); 
    }); 
} 
0

なぜPromiseを修正?

function dishOne() { 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { resolve('soup') }, 1000) 
    }) 
} 

function dishTwo() { 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { resolve('dessert') }, 1500) 
    }) 
} 

あなたwaiter機能:

function waiter(dishes, callback) { 
    return Promise.all(dishes).then(callback) 
} 

そして、あなたはこの

waiter([dishOne(), dishTwo()], function(results) { 
    // Invoked when all dishes are done 
    console.log(results) // ['soup', dessert'] 
}) 

のように理解する方がはるかに簡単にそれを使用することができます。右?

+0

おっと、申し訳ありませんが、 – Octopitus

関連する問題