我必须执行一项功能来测试3个API是否正在运行。 因此,用户将单击“测试API”按钮,它将返回每个API的状态(状态:200、500、404等)。如果API返回错误,则应显示错误堆栈。 屏幕示例:
API Status Detail
url1.com 200 -
url2.com 200 -
url3.com 500 internal server error
我的问题是,如何并行调用这3个请求并返回异步结果,我的意思是如何在不等待所有请求结果的情况下更新API请求状态的屏幕
我基于该How do I call three requests in order?,但它会同步返回结果。
*******编辑*****
那是我当前的代码
app.get('/testDependencies', function (req, res, next) {
let objTestsResul = {}
var urls = ['url1', 'url2', 'url3'];
let index = 0
while(urls.length > 0) {
let url = urls.shift();
objTestsResult[index++] = testURL(url)
}
res.send(objTestsResult)
});
每个URL的功能相同:
function testURL(URL){
fetch(URL, {
method: 'GET'
})
.then(res => {
res.json()
})
.then(json => {
console.log(json)
return json
})
.catch(error => {
return error
})
}
答案 0 :(得分:3)
Promises
(mdn)似乎是您想要的。从本质上讲,它们是回调的可读性更高的版本,它使您可以在发生其他情况时执行代码,而不必在恢复执行之前等待该触发器发生。
let endpoint1 = () => new Promise(resolve => setTimeout(() => resolve('200'), 1000));
let endpoint2 = () => new Promise(resolve => setTimeout(() => resolve('201'), 2000));
let endpoint3 = () => new Promise(resolve => setTimeout(() => resolve('500'), 1500));
document.getElementById('test').addEventListener('click', () => {
document.getElementById('status').textContent = 'test running...';
Promise.all([
endpoint1().then(a => document.getElementById('result1').textContent = a),
endpoint2().then(a => document.getElementById('result2').textContent = a),
endpoint3().then(a => document.getElementById('result3').textContent = a),
]).then(() => document.getElementById('status').textContent = 'test complete');
});
<button id="test">test</button>
<div>status: <span id="status">not running</span></div>
<div>endpoint 1: <span id="result1"></span></div>
<div>endpoint 2: <span id="result2"></span></div>
<div>endpoint 3: <span id="result3"></span></div>
答案 1 :(得分:1)
如果您可以使用Bluebird,这实际上非常简单:
const { Promise } = require('bluebird');
app.get('/testDependencies', function (req, res, next) {
Promise.map(['url1', 'url2', 'url3'], url => testURL(url)).then(results => {
res.send(results);
});
});
您只需要确保您的promise函数实际上返回了promise:
function testURL(URL) {
let start_time = new Date().getTime();
return fetch(URL, {
method: 'GET'
}).then(res => {
res.json()
}).then(json => {
console.log(json)
return json
}).catch(error => {
return error
})
}
除非已从链接所涉及的函数中显式返回它们,否则不能将依赖关系链接为依赖项。
如果您能够使用async
和await
,我还建议您这样做,这样可以大大简化原本很复杂的代码。
答案 2 :(得分:1)
Express无法发送多个响应。您将必须完成所有呼叫或使用WebSockets
来传输数据。
function testURL(URL) {
return new Promise((resolve, reject) => {
if (URL === 'url2') {
reject(new Error('Internal Server Error'));
return;
}
resolve({ status: 200 });
});
}
const main = async () => {
const urls = ['url1', 'url2', 'url3'];
// return resolved and rejected Promises because if one fails in Promise.all
// the function will throw and we won't have any access to any resolved Promises.
const results = await Promise.all(urls
.map(url => testURL(url).then(response => response).catch(error => error)));
// every error have a stack property, Set the status to whatever you want
// based on the error and store the stack and the message
const objTestsResul = results.reduce((result, cur, i) => {
result[urls[i]] = cur.stack
? { status: 500, message: cur.message, stack: cur.stack }
: cur;
return result;
}, {});
console.log(objTestsResul);
};
main();