首先处理第一个承诺,其余按完成顺序
Handle first promise first, the rest in order of completion
我需要从多个 API 中获取数据,它们对 return 数据来说都很慢。
第一个APIreturn的基础数据。调用其他 API 不需要此信息,但需要处理它们的结果。因此,虽然我可以并行发送所有请求,但我需要先处理第一个请求的结果。
例如,在 30 秒后请求 nr 1 return 秒,在 15 秒后请求 nr 2 return 秒,在 60 秒后请求 nr 3 return 秒。这意味着在 30 秒后我可以处理 nr 1 和 2 的结果,在 60 秒后我可以处理 nr 3。我更希望能够尽快处理基本信息以向用户提供反馈。
我如何在 JavaScript 中执行此操作?
我可以使用 Promise.all 等待处理,直到 所有 提取完成,但这可能需要很长时间才能显示任何结果。 (在我的示例中,60 秒。)我也可以自己启动第一次提取,并在处理完第一个回复后使用 Promise.all 进行其余操作,但这意味着其他所有内容都会被第一个请求延迟(即, 30 秒)。
我觉得解决方案是使用 async/await,但我不知道如何使用。
您可以通过几个 Promise.all
调用(正如您所怀疑的那样)结合一个显式承诺回调来相当简单地完成此操作。这部分取决于您何时要处理“其他”结果。
如果您想尽快处理“base”,但“other”只有在它们全部到达后才能得到结果
...看起来像这样:
async function doTheWork() {
const [processedBaseResult, otherResults] = await Promise.all([
baseQuery().then(rawBaseResult => processBase(rawBaseResult)),
Promise.all([
otherQuery(1),
otherQuery(2),
otherQuery(3),
])
]);
// ...process `otherResults` here, using `processedBaseResult`...
return otherResults.map(otherRaw => processOther(processedBaseResult, otherRaw));
}
并行启动所有工作,在基本结果可用时立即处理(通过 .then
回调),并等待一切完成。当一切都完成后,您可以使用处理后的基础结果来处理其他结果。
const rnd = () => Math.floor(Math.random() * 300);
const baseQuery = () =>
new Promise(resolve => setTimeout(resolve, rnd(), "base result"));
const otherQuery = (value) =>
new Promise(resolve => setTimeout(resolve, rnd(), `other result #${value}`));
const processBase = (raw) => raw + " processed";
const processOther = (baseProcessed, otherRaw) => baseProcessed + ": " + otherRaw
async function doTheWork() {
const [processedBaseResult, otherResults] = await Promise.all([
baseQuery().then(rawBaseResult => processBase(rawBaseResult)),
Promise.all([
otherQuery(1),
otherQuery(2),
otherQuery(3),
])
]);
// ...process `otherResults` here, using `processedBaseResult`...
return otherResults.map(otherRaw => processOther(processedBaseResult, otherRaw));
}
doTheWork().then(console.log).catch(console.error);
如果您想尽快处理“基本”结果并且也尽快处理“其他”结果
...看起来像这样:
async function processOther(basePromise, otherPromise) {
const [baseResult, otherRaw] = await Promise.all([basePromise, otherPromise]);
return baseResult + ": " + otherRaw;
}
async function doTheWork() {
const basePromise = baseQuery().then(rawBaseResult => processBase(rawBaseResult));
const otherResults = await Promise.all([
processOther(basePromise, otherQuery(1)),
processOther(basePromise, otherQuery(2)),
processOther(basePromise, otherQuery(3)),
]);
return otherResults;
}
这使您可以尽快开始处理每个“其他”结果,等待整个过程完成。请注意,虽然我们 await
basePromise
不止一次,但这绝对没问题;所有这些都将获得相同的履行价值。
const rnd = () => Math.floor(Math.random() * 300);
const baseQuery = () =>
new Promise(resolve => setTimeout(resolve, rnd(), "base result"));
const otherQuery = (value) =>
new Promise(resolve => setTimeout(resolve, rnd(), `other result #${value}`));
const processBase = (raw) => raw + " processed";
async function processOther(basePromise, otherPromise) {
const [baseResult, otherRaw] = await Promise.all([basePromise, otherPromise]);
return baseResult + ": " + otherRaw;
}
async function doTheWork() {
const basePromise = baseQuery().then(rawBaseResult => processBase(rawBaseResult));
const otherResults = await Promise.all([
processOther(basePromise, otherQuery(1)),
processOther(basePromise, otherQuery(2)),
processOther(basePromise, otherQuery(3)),
]);
return otherResults;
}
doTheWork().then(console.log).catch(console.error);
你可以这样做
const timeOutPromise = (data, time) => new Promise(resolve => setTimeout(() => resolve(data), time))
const promise1 = timeOutPromise("first api data", 3000);
const promise2 = timeOutPromise("second api data", 1500);
const promise3 = timeOutPromise("third api data", 5000);
promise1.then(d => console.log(d))
promise2.then(d => {
console.log(d)
promise1.then(d => {
console.log("promise 1 and 2 resolved")
})
})
promise3.then(d => {
console.log(d)
promise1.then(d => {
console.log("promise 1 and 3 resolved")
})
})
您似乎在寻找多个 Promise.all
调用,每个调用都有基本请求和其他请求之一。
const base = baseRequest().then(preprocess);
Promise.all([
Promise.all([base, firstRequest()]).then(([baseData, firstData]) => processFirst(baseData, firstData)),
Promise.all([base, secondRequest()]).then(([baseData, secondData]) => processSecond(baseData, secondData)),
Promise.all([base, thirdRequest()]).then(([baseData, thirdData]) => processThird(baseData, thirdData)),
…
]).catch(err => {
// handle (first) error from any of the above
})
(您也可以根据需要添加单独的错误处理)
这将同时触发所有请求,并在它们分别需要的数据可用时立即调用 processFirst
/ processSecond
/ processThird
。外部 Promise.all
将在所有处理完成后完成,您也可以将某些内容链接到它上面。
我需要从多个 API 中获取数据,它们对 return 数据来说都很慢。
第一个APIreturn的基础数据。调用其他 API 不需要此信息,但需要处理它们的结果。因此,虽然我可以并行发送所有请求,但我需要先处理第一个请求的结果。
例如,在 30 秒后请求 nr 1 return 秒,在 15 秒后请求 nr 2 return 秒,在 60 秒后请求 nr 3 return 秒。这意味着在 30 秒后我可以处理 nr 1 和 2 的结果,在 60 秒后我可以处理 nr 3。我更希望能够尽快处理基本信息以向用户提供反馈。
我如何在 JavaScript 中执行此操作?
我可以使用 Promise.all 等待处理,直到 所有 提取完成,但这可能需要很长时间才能显示任何结果。 (在我的示例中,60 秒。)我也可以自己启动第一次提取,并在处理完第一个回复后使用 Promise.all 进行其余操作,但这意味着其他所有内容都会被第一个请求延迟(即, 30 秒)。
我觉得解决方案是使用 async/await,但我不知道如何使用。
您可以通过几个 Promise.all
调用(正如您所怀疑的那样)结合一个显式承诺回调来相当简单地完成此操作。这部分取决于您何时要处理“其他”结果。
如果您想尽快处理“base”,但“other”只有在它们全部到达后才能得到结果
...看起来像这样:
async function doTheWork() {
const [processedBaseResult, otherResults] = await Promise.all([
baseQuery().then(rawBaseResult => processBase(rawBaseResult)),
Promise.all([
otherQuery(1),
otherQuery(2),
otherQuery(3),
])
]);
// ...process `otherResults` here, using `processedBaseResult`...
return otherResults.map(otherRaw => processOther(processedBaseResult, otherRaw));
}
并行启动所有工作,在基本结果可用时立即处理(通过 .then
回调),并等待一切完成。当一切都完成后,您可以使用处理后的基础结果来处理其他结果。
const rnd = () => Math.floor(Math.random() * 300);
const baseQuery = () =>
new Promise(resolve => setTimeout(resolve, rnd(), "base result"));
const otherQuery = (value) =>
new Promise(resolve => setTimeout(resolve, rnd(), `other result #${value}`));
const processBase = (raw) => raw + " processed";
const processOther = (baseProcessed, otherRaw) => baseProcessed + ": " + otherRaw
async function doTheWork() {
const [processedBaseResult, otherResults] = await Promise.all([
baseQuery().then(rawBaseResult => processBase(rawBaseResult)),
Promise.all([
otherQuery(1),
otherQuery(2),
otherQuery(3),
])
]);
// ...process `otherResults` here, using `processedBaseResult`...
return otherResults.map(otherRaw => processOther(processedBaseResult, otherRaw));
}
doTheWork().then(console.log).catch(console.error);
如果您想尽快处理“基本”结果并且也尽快处理“其他”结果
...看起来像这样:
async function processOther(basePromise, otherPromise) {
const [baseResult, otherRaw] = await Promise.all([basePromise, otherPromise]);
return baseResult + ": " + otherRaw;
}
async function doTheWork() {
const basePromise = baseQuery().then(rawBaseResult => processBase(rawBaseResult));
const otherResults = await Promise.all([
processOther(basePromise, otherQuery(1)),
processOther(basePromise, otherQuery(2)),
processOther(basePromise, otherQuery(3)),
]);
return otherResults;
}
这使您可以尽快开始处理每个“其他”结果,等待整个过程完成。请注意,虽然我们 await
basePromise
不止一次,但这绝对没问题;所有这些都将获得相同的履行价值。
const rnd = () => Math.floor(Math.random() * 300);
const baseQuery = () =>
new Promise(resolve => setTimeout(resolve, rnd(), "base result"));
const otherQuery = (value) =>
new Promise(resolve => setTimeout(resolve, rnd(), `other result #${value}`));
const processBase = (raw) => raw + " processed";
async function processOther(basePromise, otherPromise) {
const [baseResult, otherRaw] = await Promise.all([basePromise, otherPromise]);
return baseResult + ": " + otherRaw;
}
async function doTheWork() {
const basePromise = baseQuery().then(rawBaseResult => processBase(rawBaseResult));
const otherResults = await Promise.all([
processOther(basePromise, otherQuery(1)),
processOther(basePromise, otherQuery(2)),
processOther(basePromise, otherQuery(3)),
]);
return otherResults;
}
doTheWork().then(console.log).catch(console.error);
你可以这样做
const timeOutPromise = (data, time) => new Promise(resolve => setTimeout(() => resolve(data), time))
const promise1 = timeOutPromise("first api data", 3000);
const promise2 = timeOutPromise("second api data", 1500);
const promise3 = timeOutPromise("third api data", 5000);
promise1.then(d => console.log(d))
promise2.then(d => {
console.log(d)
promise1.then(d => {
console.log("promise 1 and 2 resolved")
})
})
promise3.then(d => {
console.log(d)
promise1.then(d => {
console.log("promise 1 and 3 resolved")
})
})
您似乎在寻找多个 Promise.all
调用,每个调用都有基本请求和其他请求之一。
const base = baseRequest().then(preprocess);
Promise.all([
Promise.all([base, firstRequest()]).then(([baseData, firstData]) => processFirst(baseData, firstData)),
Promise.all([base, secondRequest()]).then(([baseData, secondData]) => processSecond(baseData, secondData)),
Promise.all([base, thirdRequest()]).then(([baseData, thirdData]) => processThird(baseData, thirdData)),
…
]).catch(err => {
// handle (first) error from any of the above
})
(您也可以根据需要添加单独的错误处理)
这将同时触发所有请求,并在它们分别需要的数据可用时立即调用 processFirst
/ processSecond
/ processThird
。外部 Promise.all
将在所有处理完成后完成,您也可以将某些内容链接到它上面。