如何使用Promise.all解构动态数量的异步调用的结果

时间:2019-05-05 13:02:07

标签: javascript es6-promise

我需要通过Promise.all并行进行未知数量的异步调用。与此类似:

let externalCalls = [call1()];
if (someCondition1) {
  externalCalls.push(call2());
}
if (someCondition2) {
  externalCalls.push(call3());
}

然后externalCalls将被传递到Promise.all,以便它们可以并行运行。

理想情况下,我想对结果进行分解,以便我可以按名称引用结果,即

const [call1, call2, call3] = await Promise.all(externalCalls);

我知道call1将会一直存在,但是我不知道call2call3是否会在那里。因此,我想定义动态调用const的{​​{1}}结果以具有正确的属性,这可能吗?还是我陷入了一个未知长度的通用结果数组,然后必须检查结果中的每个项目以查看是哪个调用产生了它?

4 个答案:

答案 0 :(得分:1)

没有直接的方法来了解promise.all的响应来源。

但是您可以向call1,call2,call3的响应中添加更多信息

因此修改后的代码如下:

let call1 = fetch(url).then(data1 => ({...data1, source: 'call1'}));
let call2 = fetch(url).then(data2 => ({...data2, source: 'call2'}));
let call3 = fetch(url).then(data3 => ({...data3, source: 'call3'}));
let externalCalls = [call1, call2, call3, etc..];

以及您的promise.all答复中,您可以像这样检查每个返回的答复的来源。

let returnedData = {};
Promise.all(externalCalls).then(allData => {
    for(let data of allData){
        returnedData[data.source] = data;
        console.log(returnedData);
    }
});

,当您控制台返回数据时,将得到类似的内容:

 returnedData = { 
    'call1': { call1 related data},
    'call2': { call2 related data},
    'call3': { call3 related data},
}

答案 1 :(得分:1)

一方面,您已经知道根据.push()externalCallssomeCondition1的呼叫了。

但是也许以不同的方式构建externalCalls更好,因此它总是具有相同的长度:

const conditions = [true, someCondition1, etc]
const calls = [call1, call2, etc]
const externalCalls = conditions.map(
  (c, i) => c ? calls[i]() : Promise.resolve(null))
const [result1, result2, etc] = await Promise.all(externalCalls)

答案 2 :(得分:1)

如果someCondition1为false,则不推送任何内容,然后,如果someCondition2为true,则按call3(),因此您应该期望call3在返回数组的第二项中。 因此,您可以只对没有值的调用返回undefined,从而使调用在数组中具有同步索引。

let someCondition1 = false;
let someCondition2 = true;
let call1 = () => Promise.resolve("hello");
let call2 = () => Promise.resolve("world");
let call3 = () => Promise.resolve(":)");
let externalCalls = [
  call1(),
  someCondition1 ? call2() : undefined,
  someCondition2 ? call3() : undefined
];
async function resolveCalls(calls){
  const [call1, call2, call3] = await Promise.all(calls);
  console.log("call1:", call1);
  console.log("call2:", call2);
  console.log("call3:", call3);
}
resolveCalls(externalCalls);

答案 3 :(得分:0)

我的代码

const promiseFor1stAPICall = () => {
    return new Promise((resolve) => {
        return setTimeout(() => {
            resolve({ data: "1st api data" });
        }, 2000);
    });
};
const promiseFor2edAPICall = () => {
    return new Promise((resolve) => {
        return setTimeout(() => {
            resolve({ data: "2ed api data" });
        }, 2000);
    });
};

const promiseFor3rdAPICall = () => {
    return new Promise((resolve) => {
        return setTimeout(() => {
            resolve({ data: "3rd api data" });
        }, 2000);
    });
};

const promiseFor4thAPICall = () => {
    return new Promise((resolve) => {
        return setTimeout(() => {
            resolve({ data: "4th api data" });
        }, 2000);
    });
};

async function destructureFromPromiseAll() {
    const promises = [];
    promises.length = 4;
    const obj = {
        condition1: false,
        condition2: true,
    };
    promises[0] = promiseFor1stAPICall();

    if (obj.condition1) {
        promises[1] = promiseFor2edAPICall();
        promises[2] = promiseFor3rdAPICall();
    }

    if (obj.condition2) {
        promises[3] = promiseFor4thAPICall();
    }

    const data = await Promise.all(promises);
    return data;
}

async function log() {
    const data = await destructureFromPromiseAll();

    const [
        firstAPICallRes,
        secondAPICallRes,
        thirdAPICallRes,
        fourthAPICallRes,
    ] = data;

    console.log(
        firstAPICallRes,
        secondAPICallRes,
        thirdAPICallRes,
        fourthAPICallRes
    );
}

log();

============output===============
{data: '1st api data'}, undefined, undefined, {data: '4th api data'}