我要进行多个API调用,这些调用通过API进行获取,通过API将数据写入DB,通过另一个API将输出发送到前端。
我用如下所示的await编写了异步功能-
前两个应该一个接一个地运行,但是第三个可以独立运行,而不必等待前两个fetch语句完成。
let getToken= await fetch(url_for_getToken);
let getTokenData = await getToken.json();
let writeToDB = await fetch(url_for_writeToDB);
let writeToDBData = await writeToDB.json();
let frontEnd = await fetch(url_for_frontEnd);
let frontEndData = await frontEnd.json();
处理此类多个提取语句的最佳方法是什么?
答案 0 :(得分:2)
有很多方法,但是最通用的方法是将每个异步代码路径包装在一个异步函数中。您可以根据需要灵活地混合和匹配异步返回值。在您的示例中,您甚至可以内联异步iife的代码:
await Promise.all([
(async() => {
let getToken = await fetch(url_for_getToken);
let getTokenData = await getToken.json();
let writeToDB = await fetch(url_for_writeToDB);
let writeToDBData = await writeToDB.json();
})(),
(async() => {
let frontEnd = await fetch(url_for_frontEnd);
let frontEndData = await frontEnd.json();
})()
]);
答案 1 :(得分:1)
您可以使用.then()
,而不要等待:
fetch(url_for_getToken)
.then(getToken => getToken.json())
.then(async getTokenData => {
let writeToDB = await fetch(url_for_writeToDB);
let writeToDBData = await writeToDB.json();
// Carry on
})
fetch(url_for_frontEnd)
.then(frontEnd => frontEnd.json())
.then(frontEndData => {
// Carry on
})
答案 2 :(得分:1)
如果使用promise“创建者”(=返回promise的函数)而不是原始promise,则会更容易。首先,定义:
const fetchJson = (url, opts) => () => fetch(url, opts).then(r => r.json())
返回这样的“创建者”。现在,这里有两个用于串行链接和并行链接的实用程序,它们都接受原始的Promise和“创建者”:
const call = f => typeof f === 'function' ? f() : f;
const parallel = (...fns) => Promise.all(fns.map(call));
async function series(...fns) {
let res = [];
for (let f of fns)
res.push(await call(f));
return res;
}
然后,可以这样编写主要代码:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
fetchJson(url_for_getToken),
fetchJson(url_for_writeToDB),
),
fetchJson(url_for_frontEnd),
)
如果您不喜欢专用的“创建者”包装,则可以正常定义fetchJson
const fetchJson = (url, opts) => fetch(url, opts).then(r => r.json())
并在称为series
或parallel
的地方使用内联延续:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
() => fetchJson('getToken'),
() => fetchJson('writeToDB'),
),
() => fetchJson('frontEnd'), // continuation not necessary, but looks nicer
)
为使这个想法更进一步,我们可以使series
和parallel
也返回“创造者”而不是承诺。这样,我们可以构建任意嵌套的串行和并行promise的“电路”,并按顺序获得结果。完整的工作示例:
const call = f => typeof f === 'function' ? f() : f;
const parallel = (...fns) => () => Promise.all(fns.map(call));
const series = (...fns) => async () => {
let res = [];
for (let f of fns)
res.push(await call(f));
return res;
};
//
const request = (x, time) => () => new Promise(resolve => {
console.log('start', x);
setTimeout(() => {
console.log('end', x)
resolve(x)
}, time)
});
async function main() {
let chain = series(
parallel(
series(
request('A1', 500),
request('A2', 200),
),
series(
request('B1', 900),
request('B2', 400),
request('B3', 400),
),
),
parallel(
request('C1', 800),
series(
request('C2', 100),
request('C3', 100),
)
),
);
let results = await chain();
console.log(JSON.stringify(results))
}
main()
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 3 :(得分:-2)
在开始且没有writeToDB
的情况下运行独立请求(await
let writeToDB = fetch(url_for_writeToDB);
let getToken = await fetch(url_for_getToken);
let getTokenData = await getToken.json();
// ...