Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/451.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 知道我的任务结束了吗_Javascript_Node.js_Callback - Fatal编程技术网

Javascript 知道我的任务结束了吗

Javascript 知道我的任务结束了吗,javascript,node.js,callback,Javascript,Node.js,Callback,这是我的职责 function parseLinks(links, callback) { var products = []; for (var i = 0; i < links.length; i++) { request(links[i], function (error, response, body) { var product; if (!error && response.sta

这是我的职责

function parseLinks(links, callback) {

    var products = [];
    for (var i = 0; i < links.length; i++) {
        request(links[i], function (error, response, body) {
            var product;
            if (!error && response.statusCode == 200) {
                var $ = cheerio.load(body);

                // title
                var title = $('h1').text();
                if (!title)
                    var title = $('title').text();

                var description = $('meta[name="description"]').attr('content');

                product = new Product(links[0].trim(), title.trim(), description.trim());
                products.push(product);
            }
        });
    }
    callback(products) // the callback only do a console.log(products)
}
函数解析链接(链接,回调){
var乘积=[];
对于(变量i=0;i
之后,我想做一个console.log(products)来显示所有的产品。 因此,我设置了一个连接到parseLinks的回调函数,并在for循环之后调用它。问题是在for循环中,我每次调用异步函数request,因此在所有request调用结束之前调用我的回调,因此我的console.log(products)打印一个空数组

你知道怎么解决吗? 谢谢

最好的方法是使用


您必须检查是否所有异步调用都已完成。创建一个内部函数,在所有异步工作完成时调用
回调

function parseLinks(links, callback) {
    var products = [],
        numberOfItems = links.length; // numbers of linkes to be parsed

    function checkIfDone() {          // this function will be called each time link is parsed
        numberOfItems--;              // decrement the numberOfItems (number that tells us how many links left)
        if(numberOfItems === 0)       // if there are none left (all links are parsed), then call callback with the resultant array.
            callback(products);
    }

    for (var i = 0; i < links.length; i++) {
        request(links[i], function (error, response, body) {
            // ...

            checkIfDone();            // everytime a link is parsed, call checkIfDone
        });
    }
}
函数解析链接(链接,回调){
var乘积=[],
numberOfItems=links.length;//要分析的链接数
函数checkIfDone(){//每次解析链接时都会调用此函数
numberOfItems--;//减少numberOfItems(告诉我们还有多少链接的数字)
if(numberOfItems==0)//如果没有剩下(所有链接都被解析),则使用结果数组调用callback。
回收(产品);
}
对于(变量i=0;i
您可以将
checkIfDone
的逻辑直接嵌入函数
request
中。为了清晰起见,我使用了一个单独的函数。

您可以从模块中使用

简化代码:

function parseLinks(links, callback) {
    var products = [];

    async.each(links, function(link, requestCallback) {
        request(links[i], function(error, response, body) {
            //... rest of your code
            requestCallback(); //Request has ended
        });


    }, function(err) {
        //All requests ended!
        callback();
    });
}

非常感谢。你能给我解释一下吗?堆栈中的异步调用有一个特殊的顺序(它们是否按顺序执行)?@Tech for
一次启动所有异步调用。它们的完成顺序是任意的(取决于链接完成的方式)。@Tech如果你想保持顺序,你必须链接调用(当另一个调用完成时调用一个调用),或者使用
i
而不是
push
将每个产品映射到
links
数组中链接的索引。但是有一个计数器(i)以我的名义。所以完成的顺序是任意的,而不是启动的顺序?@Tech您调用
request
的顺序是正确的。但请求并不能马上完成它的工作,它只是注册一个函数,当工作完成时,该函数将被调用
for
不会花费太多时间在所有链接上调用
request
(因此您可以将其视为一次启动所有异步调用)。谢谢!你能解释一下异步是如何工作的吗?像同步器一样?@Tech
async.forEach
将数组作为其第一个参数(
links
),并将回调作为其第二个参数。对数组中的每个项运行一次回调,然后运行函数
done
,该函数在完成时作为第二个参数接收。为每个项调用
done
后,将运行
async.forEach
的第三个参数,这是您的最终回调。为了它。
function parseLinks(links, callback) {
    var products = [];

    async.each(links, function(link, requestCallback) {
        request(links[i], function(error, response, body) {
            //... rest of your code
            requestCallback(); //Request has ended
        });


    }, function(err) {
        //All requests ended!
        callback();
    });
}