javascript - 如何进行顺序 HTTP 调用?
问题描述
我需要调用几个 API 来收集和合并信息。我进行了第一个 API 调用,并根据结果对第二个 API 进行了多次调用(在循环中)。由于http请求是异步的,我丢失了信息。当第二步完成时,服务器(nodejs)已经将响应发送回客户端。
我已经尝试过以某种方式使用回调函数。这设法使对客户端的响应保持等待,但第二次调用的信息仍然丢失。我想不知何故变量没有被同步。我还使用 away/async 进行了快速测试,但我的 Javascript mojo 不足以使其运行无错误。
/* pseudo code */
function getData(var1, callback){
url= "http://test.server/bla?param="+var1;
request.get(url, function (error, response, body){
var results = [];
for(var item of JSON.parse(body).entity.resultArray) {
var o = {};
o['data1'] = item.data1;
o['data2'] = item.data2;
o['data3'] = item.data3;
getSecondStep(o, function(secondStepData){
//console.log("Callback object");
//console.log(o);
o['secondStepData'] = secondStepData;
});
results.push(o);
}
callback(results);
});
}
function getSecondStep(object, callback){
url = "http://othertest.server/foobar?param=" + object.data1;
request.get(url, function (error, response, body){
var results = [];
if(response.statusCode == 200){
for(var item of JSON.parse(body).object.array) {
var o = {}
o['data4'] = item.data4;
o['data5'] = item.data5;
results.push(o);
}
callback(results);
}
});
}
我想要的是能够将所有信息收集到一个 JSON 对象中以将其返回给客户端。然后,客户端将负责以一种很好的方式呈现它。
解决方案
我建议将 async / await 模式与request-promise-native库一起使用。
这使得 API 调用非常容易进行,并且在使用这种模式时代码更清晰。
在下面的示例中,我只是调用 httpbin API 来生成 UUID,但该原理适用于任何 API。
const rp = require('request-promise-native');
async function callAPIs() {
let firstAPIResponse = await rp("https://httpbin.org/uuid", { json: true });
console.log("First API response: ", firstAPIResponse);
// Call several times, we can switch on the first API response if we like.
const callCount = 3;
let promiseList = [...Array(callCount).keys()].map(() => rp("https://httpbin.org/uuid", { json: true }));
let secondAPIResponses = await Promise.all(promiseList);
return { firstAPIResponse: firstAPIResponse, secondAPIResponses: secondAPIResponses };
}
async function testAPIs() {
let combinedResponse = await callAPIs();
console.log("Combined response: " , combinedResponse);
}
testAPIs();
在这个简单的例子中,我们得到一个像这样的组合响应:
{
{
firstAPIResponse: { uuid: '640858f8-2e69-4c2b-8f2e-da8c68795f21' },
secondAPIResponses: [
{ uuid: '202f9618-f646-49a2-8d30-4fe153e3c78a' },
{ uuid: '381b57db-2b7f-424a-9899-7e2f543867a8' },
{ uuid: '50facc6e-1d7c-41c6-aa0e-095915ae3070' }
]
}
}
推荐阅读
- android - 如何在点击时溶解 MAPBOX 中的集群?
- unity3d - 如何在unity3d中更改画布的大小
- backend - 有没有办法使用 Knex 来拥有一列数组?
- angularjs - 离子选择动态
- sql - 表值参数“不能将参数 @Queues 声明为只读,因为它不是表值参数”
- css - CSS Grid align-items:基线在 Safari 中不起作用
- regex - 多个正则表达式查询(记事本++)
- google-chrome-devtools - HAR 文件 - 从 Chrome 开发工具网络选项卡访问“大小”列条目?
- javascript - 表单提交后如何打开模式
- eclipse - 如何在eclipse中关闭jsp文件的断线