无法实现类似节点的 async.race 功能
Can't implement node-like async.race function
我想实现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])
returns 函数应该能够处理结果。但是它 return 目前我们还没有得到任何结果的功能。
这是我的代码。问题是如何在最后一行
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?
}
}
}
}
存储函数,稍后再执行。你也在使用 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);
}
问题是我们应该 return 立即处理函数,而必须用处理函数处理的结果可能会在以后(异步)检索。所以我们应该预测两个用例:
- 在我们检索要处理的结果(
faster
函数结果)之前调用处理函数
- 我们检索结果后调用处理函数(
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
});
我想实现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])
returns 函数应该能够处理结果。但是它 return 目前我们还没有得到任何结果的功能。
这是我的代码。问题是如何在最后一行
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?
}
}
}
}
存储函数,稍后再执行。你也在使用 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);
}
问题是我们应该 return 立即处理函数,而必须用处理函数处理的结果可能会在以后(异步)检索。所以我们应该预测两个用例:
- 在我们检索要处理的结果(
faster
函数结果)之前调用处理函数 - 我们检索结果后调用处理函数(
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
});