問題
在使用 RESTful API 時,我必須發出多個請求以圍繞單個搜索檢索資料。我似乎面臨的問題是,由于結果是從大型資料庫回傳的,一些承諾需要 FOREVER 才能解決。
當前解決方案
目前,我在回圈中發出所有請求,同時將 Promise 添加到陣列中,然后使用await Promise.all()它來等待它們被解決,但這使得加載時間有時 > 30 秒,即使最早的 Promise 在幾秒鐘內解決。
我正在尋找一種可以“延遲加載”結果的方法。我確實可以訪問 restful 服務器,因此前端或后端的任何更改都會有所幫助,但是我希望更改位于前端。
編輯 1
糟糕的是,我沒有對我當前使用的代碼進行任何參考。供參考,這是我目前正在做的async function retrieve_data() {
let request_urls = [list of api endpoints to fetch]
let promises = []
for (let url of request_urls)
promises.push( fetch(url) )
await promise.all( promises )
// Do something with the returned results
}
我想要的解決方案
async function retrieve_data() {
let request_urls = [list of api endpoints to fetch]
let promises = []
for (let url of request_urls)
promises.push( fetch(url) )
let results = Promise.some_magic_function()
// Or server side
res.write(Promise.some_magic_function()) // If results are received in chunks
// Do something with the returned results
}
編輯 2
因此,雖然我確實找到
Promise.any() 并 Promise.all() 解決了一半的問題,但我似乎無法理解如何擁有一些功能,一旦它們被履行,它們就會將履行的承諾的價值添加到陣列中。雖然這些解決方案確實適用于我的用例,但我不禁認為必須有更好的解決方案。
uj5u.com熱心網友回復:
您可以在為 填充陣列時處理各個結果Promise.all,您可以使用它來了解它們何時全部完成。
如果問題中沒有任何代碼可以使用,這很棘手,但這里有一個簡單的例子:
const promises = [1, 2, 3, 4, 5].map(async (num) => {
const result = await doRequest(num);
console.log(`Immediate processing for "${result}"`);
return result; // If you're going to use the contents of the array from `Promise.all`'s fulfillment
});
const allResults = await Promise.all(promises);
console.log(`All processing done, all results:`);
for (const result of allResults) {
console.log(result);
}
現場示例:
顯示代碼片段
const rndDelay = () => new Promise((resolve) => setTimeout(resolve, Math.round(Math.random() * 1000) 100));
async function doRequest(num) {
console.log(`Requesting ${num}`);
await rndDelay();
return `Result for ${num}`;
}
async function main() {
const promises = [1, 2, 3, 4, 5].map(async (num) => {
const result = await doRequest(num);
console.log(`Immediate processing for "${result}"`);
return result; // If you're going to use the contents of the array from `Promise.all`'s fulfillment
});
const allResults = await Promise.all(promises);
console.log(`All processing done, all results:`);
for (const result of allResults) {
console.log(result);
}
}
main()
.catch((error) => console.error(error));
.as-console-wrapper {
max-height: 100% !important;
}
請注意,我們給出的回呼map(在本例中)是一個async函式,因此它回傳一個 Promise,我們可以await在其中使用。
如果您不能async在創建承諾的地方使用包裝器,那不是問題,您可以回退到.then:
const promises = [1, 2, 3, 4, 5].map((num) => {
return doRequest(num)
.then((result) => {
console.log(`Immediate processing for "${result}"`);
return result; // If you're going to use the contents of the array from `Promise.all`'s fulfillment
});
});
const allResults = await Promise.all(promises);
console.log(`All processing done, all results:`);
for (const result of allResults) {
console.log(result);
}
顯示代碼片段
const rndDelay = () => new Promise((resolve) => setTimeout(resolve, Math.round(Math.random() * 1000) 100));
async function doRequest(num) {
console.log(`Requesting ${num}`);
await rndDelay();
return `Result for ${num}`;
}
async function main() {
const promises = [1, 2, 3, 4, 5].map((num) => {
return doRequest(num)
.then((result) => {
console.log(`Immediate processing for "${result}"`);
return result; // If you're going to use the contents of the array from `Promise.all`'s fulfillment
});
});
const allResults = await Promise.all(promises);
console.log(`All processing done, all results:`);
for (const result of allResults) {
console.log(result);
}
}
main()
.catch((error) => console.error(error));
.as-console-wrapper {
max-height: 100% !important;
}
uj5u.com熱心網友回復:
將請求提取到不同的異步函式并在它們解決時處理它們:
// Request that responds in 2 seconds
async function req1() {
let response = await http.get(`${serverRoot}/api/req1`);
// Work on response from req 1. Everything below this line executes after 2'
}
//Request that responds in 30 seconds
async function req2() {
let response = await http.get(`${serverRoot}/api/req2`);
// Work on response from req 1. Everything below this line executes after 30'
}
//Request that responds in 10 seconds
async function req3() {
let response = await http.get(`${serverRoot}/api/req3`);
// Work on response from req 1. Everything below this line executes after 30'
}
然后您可以繼續將它們全部添加到一個陣列中并等待它們全部完成,例如,隱藏一個加載指示器:
loading = true;
//Notice that we have to invoke the functions inside the array
await Promise.all([req1(), req2(), req3()]);
//Everything below this line will run after the longest request is finished, 30 seconds
loading = false;
uj5u.com熱心網友回復:
你可以利用Promise.race這里。
該
Promise.race()方法回傳一個承諾,一旦可迭代中的一個承諾履行或拒絕,該承諾就會履行或拒絕,并帶有來自該承諾的值或原因。
Promise.any是相似的,但是:
此外,與回傳第一個結算值(履行或拒絕)的 Promise.race() 不同,此方法回傳第一個履行的值。此方法將忽略所有被拒絕的 Promise,直到第一個 Promise 完成。
這是一些示例代碼:
function greedyPromiseAll(promises, onResolved) {
return new Promise((resolveAll, reject) => {
while (promises.length > 0) {
const resolved = Promise.race(promises);
promises.splice(promises.indexOf(resolved), 1);
onResolved(resolved);
}
resolveAll();
});
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513491.html
