[英]Delay each loop iteration in node js, async
我有以下代碼:
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);
});
有沒有人建議如何延遲for loop
中的每個循環迭代? 比如說,代碼在每次迭代完成后等待10秒。 我嘗試了setTimeout
但沒有管理它。
您可以按以下間隔設置執行代碼的超時時間,如下所示:
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);
}
所以第一個立即運行(間隔* 0為0),第二個運行十秒后運行等。
您需要將i
作為setTimeout()
的最后一個參數發送,以便將其值綁定到函數參數。 否則,訪問數組值的嘗試將超出范圍,您將得到undefined
。
另一種方法是使用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
延遲多個頁面提取 我是異步庫的忠實粉絲,我已經使用了很長時間。 但是,現在有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()
和fetchUrls()
工作原理之前,讓我們首先回答你在獲取下一頁之前如何等待的問題。 睡眠功能非常簡單:
async function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
您可以在此處獲得有關其工作原理的完整說明。
好的,回到其他功能。 request
庫具有啟用了承諾的版本,您可以將其與async/await
。 我們來看看fetchPage()
如何實現的:
async function fetchPage(url) {
return await request({
url: url,
transform: (body) => cheerio.load(body)
});
}
由於request
正在返回一個承諾,我們可以await
它。 我也有機會使用transform
屬性,它允許我們在解析promise之前轉換響應體。 我將它傳遞給Cheerio,就像你在代碼中所做的那樣。
最后, fetchUrls()
可以在解析其promise之前調用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();
要使用promises request
,請按以下方式安裝:
npm install request
npm install request-promise-native
然后在代碼中require("request-promise-native")
,如上例所示。
由於你已經在使用async
, async.wilst
可以很好地替代for
。
whilst
是一個異步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
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.