当前位置: 代码迷 >> JavaScript >> 无法实现类似节点的 async.race 功能
  详细解决方案

无法实现类似节点的 async.race 功能

热度:34   发布时间:2023-06-05 11:45:04.0

我想实现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?
            }
        }
    }
}

存储函数,稍后再执行。 当您应该简单地接受一个数组时,您也在使用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); }

问题是我们应该立即返回处理程序函数,而必须用处理程序函数处理的结果可能会在稍后(异步)检索。 所以我们应该预测两个用例:

  1. 在我们检索要处理的结果( faster函数结果)之前调用 Handler-function
  2. 获取结果后调用处理函数( 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
});
  相关解决方案