首先处理第一个承诺,其余按完成顺序

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 将在所有处理完成后完成,您也可以将某些内容链接到它上面。