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
(因此您可以将其视为一次启动所有异步调用)。谢谢!你能解释一下异步是如何工作的吗?像同步器一样?@Techasync.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();
});
}