为了账号安全,请及时绑定邮箱和手机立即绑定

异步函数返回一个承诺数组而不是实际的值数组

异步函数返回一个承诺数组而不是实际的值数组

临摹微笑 2021-10-14 15:48:00
我有一个函数,它将接受一个整数数组,然后它将调用另一个函数,该函数将接受一个整数并进行一些检查并返回一个承诺来解决它。我知道 getDataById 函数并不依赖于做异步工作,但在我看来这只是例子..这是我的代码:function getDataById(id) {    return new Promise((resolve, reject) => {        if (id > 0) resolve(id * 10);        if (id <= 0) reject("wrong input");    })}async function callService(idList) {    return await idList.map((id) => getDataById(id));}let teamIDList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -1, -2, -3, -4];callService(teamIDList).then(res => {    console.log(res);});我希望它会返回一个新数字数组和一些字符串。但它返回了一系列承诺。
查看完整描述

1 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

await 当你给它一个数组时并没有做任何特别的事情,它只是将数组包装在一个已解决的承诺中。


要等待承诺解决,请使用Promise.all:


async function callService(idList) {

    return await Promise.all(idList.map((id) => getDataById(id)));

}

交替:


function callService(idList) {

    return Promise.all(idList.map((id) => getDataById(id)));

}

(旁注:不需要那个箭头函数:


return await Promise.all(idList.map(getDataById));

)

请注意,它们都按以下顺序执行操作:

  • getDataById为每个调用id

  • 等待所有这些承诺都实现,或者其中一个失败

  • 如果它们都实现了,则使用结果数组来解析callService的承诺(记住,async函数总是返回承诺)

如果您想getDataById在对 进行下一次调用之前等待每个调用完成getDataById,您可以使用一个简单的循环来完成:

// **IF** you wanted to wait for each `getDataById` call to finish

// before starting the next

async function callService(idList) {

    const result = [];

    for (const id of idList) {

        result.push(await getDataById(id));

    }

    return result;

}

(reduce如果你愿意,你也可以把它硬塞进去,但它不会给你买任何东西。)


但我认为你想要上面的第一个代码块,并行启动所有调用并等待它们完成。


你在评论中说你的老板不希望你使用,Promise.all因为如果任何承诺拒绝,它就会拒绝。确实如此,确实如此。如果你不想那样,你可能想allSettled改用。这是第 4 阶段的提案(例如,在 JavaScript 引擎中积极实施),它很容易被 polyfill。


async function callService(idList) {

    return await Promise.allSettled(idList.map(getDataById));

}

交替:


function callService(idList) {

    return Promise.allSettled(idList.map(getDataById));

}

结果是一个对象数组,其中已履行的承诺如下所示:


{

    status: "fulfilled",

    value: (the value)

}

被拒绝的看起来像这样:


{

    status: "fulfilled",

    reason: (the rejection reason)

}

显然,如果你想转换那个数组,你可以很容易地做到这一点。例如,如果您想返回null无法检索的那些:


async function callService(idList) {

    return (await Promise.allSettled(idList.map(getDataById)))

           .map(entry => entry.status === "fulfilled" ? entry.value : null);

}

或者,如果您想过滤掉它们:


async function callService(idList) {

    return (await Promise.allSettled(idList.map(getDataById)))

           .map(entry => entry.status === "fulfilled" ? entry.value : null)

           .filter(entry => entry !== null);

}

如果你想同时过滤和映射,我们可以稍微滥用flatMap:-)


async function callService(idList) {

    return (await Promise.allSettled(idList.map(getDataById)))

           .flatMap(entry => entry.status === "fulfilled" ? entry.value : []);

}


查看完整回答
反对 回复 2021-10-14
  • 1 回答
  • 0 关注
  • 131 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信