arrays - for循环nodejs中的异步
问题描述
我正在尝试访问 api,我将不得不根据需要迭代的页码多次运行 api 调用,以下是我正在使用的代码以及如何将所有响应推送到数组中.
由于 nodeJs 是单线程的,它不等待来自 api 的响应。我该如何解决这个问题并确保所有响应值都被推送到数组中
在 for 循环中,我想要包含 api 响应的所有值的最终数组。所以,我检查总页值和响应页码是否匹配,这意味着这将是最后一页,我将数组推送到另一个函数,但是当我这样做时,它没有所有值,因为 nodejs 不等待api 响应。
const fs = require('fs');
var pepKey = 'asdfasdfasd';
var pepResponse;
var pepTimecards = [];
pep();
function pep(){
var options = {
headers: {
"content-type": "application/json",
},
agentOptions: {
pfx: fs.readFileSync('./certificate/asdfsdaf.p12'),
passphrase: 'asdasdsda'
}
};
request.get('https://source.asdfasdf.io/api/organisations/asdfasdf/timecard_keys?timecard_type=Flex',options, (err, res, body) => {
if (err) { return console.log(err); }
pepResponse = JSON.parse(body)
pepTimecards = pepResponse.data;
if(pepResponse.pages > 1){
for(let i=2;i<=pepResponse.pages;i++){
var url = 'https://source.`pepme`.io/api/organisations/sdfsadf/timecard_keys?timecard_type=Flex&page='+pageNo;
request.get(url,options, (err, res, body) => {
if (err) { return console.log(err); }
body = JSON.parse(body)
pepTimecards = pepTimecards.concat(body.data)
if(pepResponse.pages == body.page){
console.log(pepResponse.pages)
console.log(body.page +"body page")
console.log(pepTimecards)
}
});
}
}else{
}
});
}
解决方案
使用 request-promise 库,它提供了请求库的承诺版本。然后,您可以在 for
循环中使用 async/await 来序列化您的操作:
更新的答案与 OP 问题中的编辑代码一起使用
const fs = require('fs');
const rp = require('request-promise');
const pepKey = 'asdfasdfasd';
pep().then(pepTimecards => {
// the timecard data is valid in here
console.log(pepTimecards);
}).catch(err => {
console.log(err);
});
async function pep() {
let timecards = [];
const options = {
headers: {
"content-type": "application/json",
},
agentOptions: {
pfx: fs.readFileSync('./certificate/asdfsdaf.p12'),
passphrase: 'asdasdsda'
},
json: true,
uri: 'https://source.asdfasdf.io/api/organisations/asdfasdf/timecard_keys?timecard_type=Flex'
};
let pepResponse = await rp(options);
timecards = pepResponse.data;
if (pepResponse.pages > 1) {
for (let i = 2; i <= pepResponse.pages; i++) {
options.uri = 'https://source.`pepme`.io/api/organisations/sdfsadf/timecard_keys?timecard_type=Flex&page='+pageNo;
let body = await rp(url, options);
// add body.data onto the existing array
timecards.push(...body.data);
}
} else {
}
console.log(pepResponse.pages)
console.log(timecards)
return timecards;
}
OP 在他们的问题中编辑代码之前的先前答案:
const rp = require('request-promise');
// I'm assuming this is some sort of method definition on a class, otherwise it needs the function keyword
async pageno(pageNo) {
for (let i=2;i<=pepResponse.pages;i++){
try {
options.uri = 'https://test/timecard_keys?timecard_type=asdas&page='+pageNo;
// let request-promise parse the json for you automatically
options.json = true;
let body = await rp(options);
pepTimecards = pepTimecards.concat(body.data)
if (pepResponse.pages == body.page){
console.log(pepResponse.pages)
console.log(body.page +"body page")
console.log(pepTimecards)
}
} catch(e) {
// decide what to do for error handling
// this will log and rethrow so the caller will get a rejected promise
console.log(e);
throw e;
}
}
// return some value here to be the resolved value of the returned promise
return pepTimecards;
}
在您的代码中,不清楚options
, pepTimecards
,pepResponse
变量的声明位置。它们可能应该在这里声明为局部变量或传递给函数和/或从你的函数返回。
修改总结:
- 添加
async
到方法声明,以便我们可以使用await
. - 将 request-promise 库加载到
rp
变量中 - 添加
options.json = true
到让 request-promise 库自动为我们解析 JSON 结果 - 更改
rp()
为仅使用选项结构(向其中添加 URL) - 添加 try/catch 以捕获来自 的任何错误
await
,记录它们,然后重新抛出,这样pageno()
将返回一个承诺,如果有错误则拒绝(如果需要,您可以自定义出现错误时的行为) - 添加一个返回值,以便对 Promise 有有意义的解析值(您不应该像现在这样使用副作用编程(修改未传入、在本地声明或返回的变量)。
您仍然需要解决的问题:
- 停止使用副作用编程来修改未传入、未在本地声明且未返回的自由变量。这是设计代码的不好方法。您没有从调用代码或定义这些其他变量的位置显示足够的整体上下文,以就应该如何完成提出具体建议。
- 如果其中一个请求出现错误,请确定您的错误处理策略是什么,并实施该策略并进行适当的处理。
推荐阅读
- javascript - vue中如何在数组中显示数组
- python - 使用 pandas 和 matplotlib 绘制特定范围的值
- python - Python数据框中的合并列
- javascript - 在自定义 Java React Native 模块中调用 moveTaskToBack() 以编程方式将应用程序移动到后台
- python - Python 正则表达式匹配列表中的多个单词
- c# - 索引(ElasticClient.IndexMany())抛出 StackOverflowException
- python - 在 ManyToManyField 中计算喜欢 - django rest 框架
- postgis - 通过外部 Geoserver 连接到本地 PC 中的 postgis 数据库
- android - 为什么更新不存在的 firestore 文档永远不会失败?
- php - 为什么流明不能识别正在发送的字段