Javascript 延迟节点js中的每个循环迭代,异步
我的代码如下:Javascript 延迟节点js中的每个循环迭代,异步,javascript,node.js,for-loop,Javascript,Node.js,For Loop,我的代码如下: var request = require('request'); var cheerio = require ("cheerio"); var async= require("async"); var MyLink="www.mylink.com"; async.series([ function(callback){ request(Mylink, function (error, response, body) {
var request = require('request');
var cheerio = require ("cheerio");
var async= require("async");
var MyLink="www.mylink.com";
async.series([
function(callback){
request(Mylink, function (error, response, body) {
if (error) return callback(error);
var $ = cheerio.load(body);
//Some calculations where I get NewUrl variable...
TheUrl=NewUrl;
callback();
});
},
function(callback){
for (var i = 0; i <=TheUrl.length-1; i++) {
var url = 'www.myurl.com='+TheUrl[i];
request(url, function(error, resp, body) {
if (error) return callback(error);
var $ = cheerio.load(body);
//Some calculations again...
callback();
});
};
}
], function(error){
if (error) return next(error);
});
var request=require('request');
var cheerio=要求(“cheerio”);
var async=require(“异步”);
var MyLink=“www.MyLink.com”;
异步系列([
函数(回调){
请求(Mylink、函数(错误、响应、正文){
if(error)返回回调(error);
var$=总负荷(车身);
//我得到NewUrl变量的一些计算。。。
TheUrl=NewUrl;
回调();
});
},
函数(回调){
对于(var i=0;i,您可以按如下所示的递增间隔设置代码执行超时:
var interval = 10 * 1000; // 10 seconds;
for (var i = 0; i <=TheUrl.length-1; i++) {
setTimeout( function (i) {
var url = 'www.myurl.com='+TheUrl[i];
request(url, function(error, resp, body) {
if (error) return callback(error);
var $ = cheerio.load(body);
//Some calculations again...
callback();
});
}, interval * i, i);
}
npm install request
npm install request-promise-native
var interval=10*1000;//10秒;
对于(var i=0;i,因为您已经在使用async
,async.wilst
可以很好地替代for
while
是一个类似于while
的异步函数。每次迭代仅在上一次迭代调用其完成回调后运行。在这种情况下,我们可以使用setTimeout
将完成回调的执行延迟10秒
var i = 0;
async.whilst(
// test to perform next iteration
function() { return i <= TheUrl.length-1; },
// iterated function
// call `innerCallback` when the iteration is done
function(innerCallback) {
var url = 'www.myurl.com='+TheUrl[i];
request(url, function(error, resp, body) {
if (error) return innerCallback(error);
var $ = cheerio.load(body);
//Some calculations again...
// wait 10 secs to run the next iteration
setTimeout(function() { i++; innerCallback(); }, 10000);
});
},
// when all iterations are done, call `callback`
callback
);
var i=0;
异步的(
//测试以执行下一次迭代
function(){return i另一种选择是使用async.eachSeries
。例如:
async.eachSeries(TheUrl, function (eachUrl, done) {
setTimeout(function () {
var url = 'www.myurl.com='+eachUrl;
request(url, function(error, resp, body) {
if (error) return callback(error);
var $ = cheerio.load(body);
//Some calculations again...
done();
});
}, 10000);
}, function (err) {
if (!err) callback();
});
使用async/await
我非常喜欢异步库,我已经使用了很长时间。但是,现在有了。您的代码变得更容易阅读。例如,这将是您的主要功能:
const urls = await fetchUrls(INITIAL_URL);
for (const url of urls) {
await sleep(10000);
const $ = await fetchPage(url);
// do stuff with cheerio-processed page
}
更好,不是吗?在我详细介绍fetchPage()
和fetchurl()
如何工作之前,让我们先回答一下您关于如何等待才能获取下一页的问题。sleep函数非常简单:
async function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
你可以在我的另一个答案中得到它是如何工作的完整解释
好的,回到其他函数。请求
库有一个启用承诺的版本,可以与async/await
一起使用。让我们看看fetchPage()
是如何实现的:
async function fetchPage(url) {
return await request({
url: url,
transform: (body) => cheerio.load(body)
});
}
由于request
正在返回一个承诺,我们可以等待它。我还借此机会使用transform
属性,它允许我们在解析承诺之前转换响应体。我正在通过Cheerio传递它,就像您在代码中所做的那样
最后,fetchUrls()
只需调用fetchPage()
并对其进行处理以获取URL数组,然后再解析其承诺。以下是完整代码:
const
request = require("request-promise-native"),
cheerio = require("cheerio");
const
INITIAL_URL = "http://your-initial-url.com";
/**
* Asynchronously fetches the page referred to by `url`.
*
* @param {String} url - the URL of the page to be fetched
* @return {Promise} promise to a cheerio-processed page
*/
async function fetchPage(url) {
return await request({
url: url,
transform: (body) => cheerio.load(body)
});
}
/**
* Your initial fetch which will bring the list of URLs your looking for.
*
* @param {String} initialUrl - the initial URL
* @return {Promise<string[]>} an array of URL strings
*/
async function fetchUrls(initialUrl) {
const $ = await fetchPage(initialUrl);
// process $ here and get urls
return ["http://foo.com", "http://bar.com"];
}
/**
* Clever way to do asynchronous sleep.
* Check this: https://stackoverflow.com/a/46720712/778272
*
* @param {Number} millis - how long to sleep in milliseconds
* @return {Promise<void>}
*/
async function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
async function run() {
const urls = await fetchUrls(INITIAL_URL);
for (const url of urls) {
await sleep(10000);
const $ = await fetchPage(url);
// do stuff with cheerio-processed page
}
}
run();
然后在你的代码中加入require(“request promise native”)
,就像上面的例子一样。为什么我不能把最后一行从},interval*I,I);
改成},interval*1,I);
从I改成1
?如果我想要一个恒定的interval,那么代码就不能工作。setTimeout()
立即返回。它不会坐在那里等待超时,然后再将控制权返回到for
循环。因此,如果使用interval*1
(与interval
相同),那么您将在未来十秒钟内一次性运行所有操作(或多或少——它们将相隔几毫秒,但仅此而已)。但如果使用interval*i
,则第一次“立即”通过,“未来十秒”循环第二次“未来二十秒”第三次,等等。好的,尝试了interval*1
,但没有结果…但我理解你的意思!Thansk。请注意,setTimeout有一个最大值,如果它达到2147483647,它将中断。是否可以在特定时间设置延迟?例如,每30分钟一次?