我想实现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?
}
}
}
}
答案 0 :(得分:1)
存储该功能,然后再执行。当你应该使用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);
}
&#13;
答案 1 :(得分:0)
问题是我们应该立即返回handler-function,而必须使用handler-function处理的结果可以稍后(异步)检索。所以我们应该预测两个用例:
faster
函数结果)之前调用Handler函数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
});