问题描述
我想实现async.race
功能
/*
* Takes array of functions and returns a handler-function of result of the fastest btw arguments
*/
async.race([slower, faster])(function(err, winner) {
console.log(winner); // I'm faster
});
function slower(callback) {
setTimeout(callback.bind(null, null, "I'm slower"), 1000);
}
function faster(callback) {
setTimeout(callback.bind(null, null, "I'm faster"), 10);
}
这里的问题是async.race([slower, faster])
返回应该能够处理结果的函数。
但是它在我们还没有得到任何结果的那一刻返回函数。
这是我的代码。 问题是如何在最后一行
var async = {
race: function() {
var args = Array.prototype.slice.call(arguments),
finished = false,
i, winner_err, winner_data;
var callback = function(err, data) {
if (finished) return;
else finished = true;
winner_err = err;
winner_data = data;
}
for (i = 0; i < args.length; i++) {
args[i](function(err, data) {
if (finished) return;
else finished = true;
});
}
return function(fn) {
if (finished) {
fn(winner_err, winner_data);
} else {
//QUESTION: how to be here. I need return function with not ready `winner_data` and check in while/setInterval when the results will appear?
}
}
}
}
1楼
Kevin B
1
2015-07-30 15:54:46
存储函数,稍后再执行。
当您应该简单地接受一个数组时,您也在使用arguments
。
var async = { race: function(arr) { var finished = false, i, winner_err, winner_data, cb = console.log.bind(console); for (i = 0; i < arr.length; i++) { arr[i](function(err, data) { if (finished) {return;} else {finished = true; cb(err, data);} }); } return function(fn) { cb = fn; } } } async.race([slower, faster])(function(err, winner) { console.log(err, winner); // I'm faster }); function slower(callback) { setTimeout(callback.bind(null, null, "I'm slower"), 1000); } function faster(callback) { setTimeout(callback.bind(null, null, "I'm faster"), 10); }
2楼
VB_
0
已采纳
2015-07-30 20:32:06
问题是我们应该立即返回处理程序函数,而必须用处理程序函数处理的结果可能会在稍后(异步)检索。 所以我们应该预测两个用例:
-
在我们检索要处理的结果(
faster
函数结果)之前调用 Handler-function -
获取结果后调用处理函数(
faster
函数结果)
最后我以下一个实现结束:
var async = {
// @param array - array of a functions
// @return returns a function which accept handler-function as
// an argument. The handler function will handle the result of the
// fastest btw {@param array} functions
race: function(arr) {
// indicates if the first (fastest) function is completed.
// If yes - there is no sense to handle another functions results
var finished = false,
// Returned errors / data of the first (fastest) function
winner_err, winner_data,
// callback which will handle the results of the fastest function
cb, i;
var retur_func = function(fn) {
// For the case if `smth_like_promise` (see Usage section) will be called
// before `faster` will be completed
cb = fn;
// For the case if `faster` will be completed before
// `smth_like_promise` will be called
if (retur_func.redefined) retur_func.redefined(fn);
};
// callback which handle the result of each separate function that participates in race
var callback = function(err, data) {
if (finished) return;
finished = true;
// Tricky situation: we have data to be handled, but haven't handler function
if (!cb) {
// We pass `return_func` to the client and can't redefine it.
// So we redefine it property, which will be called instead function in future
retur_func.redefined = function(fn) {
fn(err, data);
}
} else {
cb(err, data);
}
}
// Start race! Afterwards only the first function results should be
// handled with `retur_func` function
for (i = 0; i < arr.length; i++) {
arr[i](callback);
}
return retur_func;
}
}
用法:
var slower = function(cb) {
setTimeout(cb.bind(null, null, "I'm slower"), 1000);
}
var faster = function(cb) {
setTimeout(cb.bind(null, null, "I'm faster"), 10);
}
var smth_like_promise = async.race([slower, faster]);
// you may call `smth_like_promise` immediately or wait until passed functions (`faster` or `slower`) will be completed
smth_like_promise(function(err, winner) {
alert(winner); // I'm faster
});