Javascript 使我的异步代码与setTimeout同步。我需要承诺吗?
我正在为一个特定的网站构建一个数据刮板。因为我只想每10秒发出一个请求,所以我将其设置为setTimeout循环,该循环将url作为我手动输入的url数组的参数。在回调中,它请求此url并解析响应,将数据推送到一个新的结构化数组中,以便最终将其转换为csv。我将粘贴下面的完整代码以及我的依赖项 问题是,这些请求中大约有五分之一返回为未定义。我认为超时函数会处理这个问题,程序会同步运行。我显然错了。研究这一点,我发现很多人使用承诺依赖来订购异步请求。我的问题是:这有必要吗?或者我可以调整回调/设置超时,使其在不添加其他依赖项的情况下工作 编辑由于不清楚,我在这里复制的正是我希望此应用程序执行的操作: 我希望程序接受一个请求,返回一个json字符串,解析该json字符串中的数据,将该数据添加到数组中,并将该数组导出为csv。我想循环这个功能,这样它就可以对一长串URL执行此操作,但我希望它一次只发出一个请求,并等待迭代到下一个请求,直到从初始响应中收集到所需的数据。我只想每10秒发送一个请求 这是我的密码:Javascript 使我的异步代码与setTimeout同步。我需要承诺吗?,javascript,node.js,asynchronous,request,promise,Javascript,Node.js,Asynchronous,Request,Promise,我正在为一个特定的网站构建一个数据刮板。因为我只想每10秒发出一个请求,所以我将其设置为setTimeout循环,该循环将url作为我手动输入的url数组的参数。在回调中,它请求此url并解析响应,将数据推送到一个新的结构化数组中,以便最终将其转换为csv。我将粘贴下面的完整代码以及我的依赖项 问题是,这些请求中大约有五分之一返回为未定义。我认为超时函数会处理这个问题,程序会同步运行。我显然错了。研究这一点,我发现很多人使用承诺依赖来订购异步请求。我的问题是:这有必要吗?或者我可以调整回调/设置
var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var app = express();
var arr = [];
var url = //A bunch of urls that I'm leaving out to conserve space
i = 0;
function timeout() {
setTimeout(function() {
request(url[i], function(error, response, html){
if(error){
console.log(error);
} else {
var $ = cheerio.load(html);
var company, industry, size, website, type;
var inArr = [];
$('div .image-wrapper img').filter(function(){
var data = $(this);
company = data.attr('alt');
inArr.push("\"" + company + "\"");
})
$('.industry p').filter(function(){
var data = $(this);
industry = data.text();
inArr.push("\"" + industry + "\"");
})
$('.company-size p').filter(function(){
var data = $(this);
size = data.text();
inArr.push("\"" + size + "\"");
})
$('.website p a').filter(function(){
var data = $(this);
website = data.text();
inArr.push("\"" + website + "\"");
})
$('.type p').filter(function(){
var data = $(this);
type = data.text();
inArr.push("\"" + type + "\"");
})
arr.push(inArr);
console.log("I just sourced data for " + company);
if (i === url.length - 1) {
clearTimeout(timeout);
console.log("All done!")
var csvContent;
arr.forEach(function(infoArray, index){
dataString = infoArray.join(",");
csvContent += index < arr.length ? dataString+ "\n" : dataString;
});
fs.writeFile('output.csv', csvContent, function(err){
console.log('File successfully written! - Check your project directory for the output.csv file');
});
} else {
i++;
timeout();
}
}
});
}, 10000);
};
timeout();
var express=require('express');
var fs=需要('fs');
var请求=要求(“请求”);
var cheerio=需要('cheerio');
var-app=express();
var-arr=[];
var url=//为节省空间而省略的一组url
i=0;
函数超时(){
setTimeout(函数(){
请求(url[i],函数(错误,响应,html){
如果(错误){
console.log(错误);
}否则{
var$=cheerio.load(html);
var公司、行业、规模、网站、类型;
var-inar=[];
$('div.image wrapper img').filter(函数(){
var数据=$(此);
公司=data.attr('alt');
内部推送(“\”+公司+“\”);
})
$('.industry p').filter(函数(){
var数据=$(此);
industry=data.text();
内部推送(“\”+行业+“\”);
})
$('.company size p').filter(函数(){
var数据=$(此);
size=data.text();
一次推送(“\”+大小+“\”);
})
$('.website p a').filter(函数(){
var数据=$(此);
网站=data.text();
推送(“\”+网站+“\”);
})
$('.type p').filter(函数(){
var数据=$(此);
type=data.text();
自动推送(“\”+类型+“\”);
})
arr.push(inArr);
log(“我刚刚为”+公司获取了数据);
if(i==url.length-1){
clearTimeout(超时);
log(“全部完成!”)
var CSV含量;
arr.forEach(函数(infoArray,索引){
dataString=infoArray.join(“,”);
csvContent+=索引
尝试调整js
以声明引用setTimeout
的变量。在问题的js
中,调用clearTimeout()
时使用timeout
作为参数,尽管timeout
是一个函数,而不是对timeout()
中调用的setTimeout
的引用。在下面的js
中,t
被声明为timeout
函数外部的变量,设置为setTimeout
内timeout()调用的引用
看
语法
var timeoutID = window.setTimeout(func, [delay, param1, param2, ...]);
var timeoutID = window.setTimeout(code, [delay]);
var arr=[];
var url=[0,1,2,3,4,5,6,7,8,9];
var i=0;
var t=null;
函数超时(){
t=设置超时(函数(){
(功能(){
var-inar=[];
内推(一)
arr.push(inArr);
log(“我刚刚为“+I,t”获取了数据);
if(i==url.length-1){
清除超时(t);
log(“全部完成!”,i,url.length-1,arr)
}否则{
i++;
超时();
}
}());
},1000);//将stacksnippets的持续时间缩短为“1000”
};
超时()代码>如果这里真正的问题是您希望一个接一个地发送请求,但间隔不超过10秒,那么您可以通过制作一个小包装器函数来完成,该函数告诉您下次调用的时间:
var request = require('request');
function requestNext(url, callback, delay, nextCallback) {
var start = Date.now();
request(url, function(error, response, html) {
callback(error, response, html);
var elapsed = Date.now() - start;
var wait = Math.max(delay - elapsed, 0);
// schedule next call to request()
setTimeout(nextCallback, wait);
});
}
然后,只需调用requestNext(),指定延迟时间和第二个回调,该回调将告诉您何时进行下一次调用
然后,在您的特殊情况下,您可以将其与如下重复函数一起使用:
function getURLs(urls, delay, processCallback, doneCallback) {
var index = 0;
var data = [];
function next() {
if (index < urls.length) {
requestNext(urls[index++], function(err, response, html) {
// need to decide what you want do for error handling here
// continue? stop further processing?
data.push(processCallback(err, response, html));
}, delay, next);
} else {
doneCallback(null, data);
}
}
next();
}
getURLs(urlArray, 10000, processResult, function(err, dataArray) {
if (!err) {
// results are in dataArray
}
});
function processResult(err, response, html) {
// your code to process a page here
// return the final result as a return value and it will be collected for you
}
“问题是大约五分之一的请求返回为未定义的。”clearTimeout(timeout)的预期结果是什么代码>setTimeout
在timeout
内未声明初始或以后设置的函数