Promise.all 用于 Javascript 中的对象

问题描述 投票:0回答:5

Promise.all 可以把

[Promise a, Promise b]
变成
Promise [a, b]
,超级有用,但是还有没有办法把
{a: Promise a, b: Promise b}
变成
Promise {a, b}

用例是:

我有一个函数可以从网站加载一些文件,并在失败时返回错误消息。 这意味着,它的签名是

information -> {values: values, messages: messages}

但是整个检查是异步的,所以结果是

information -> {values: Promise values, messages: promise messages}

javascript asynchronous promise
5个回答
4
投票

这是我的超级简单的解决方案:

export const objectZip = (keys, values) =>
  keys.reduce(
    (others, key, index) => ({
      ...others,
      [key]: values[index],
    }),
    {}
  );

export const objectPromise = async obj =>
  objectZip(Object.keys(obj), await Promise.all(Object.values(obj)));

2
投票

您可以手动完成:

function objectPromise(obj) {
    return Promise.all(Object.keys(obj).map(function (key) {
        return Promise.resolve(obj[key]).then(function (val) {
            return {key: key, val: val};
        });
    })).then(function (items) {
        var result = {};
        items.forEach(function (item) {
            result[item.key] = item.val;
        });
        return result;
    });
}

用法

var testObj = {
    a: Promise.resolve("a"),
    b: Promise.resolve("b"),
    c: "c"
};

objectPromise(testObj).then(function (obj) {
    console.log(obj);
});
//> { a: 'a', b: 'b', c: 'c' }

ES6 语法中的相同内容,如果您愿意的话:

var objectPromise = obj => Promise.all(
    Object
    .keys(obj)
    .map(key => Promise.resolve(obj[key]).then(val => ({key: key, val: val})))
).then(items => {
    let result = {};
    items.forEach(item => result[item.key] = item.val);
    return result;
});

0
投票

据我所知不,但你可以准备一个返回对象,你就会知道它何时准备好

function multipleAsyncJobs(){
    ret = {};
    var a = new Promise(function(resolve, reject){
        ret.a = someVal; // set 
        resolve();
    })
    var b = new Promise(function(resolve, reject){
        ret.b = someVal; // set 
        resolve();
    })
    return new Promise(function (resolve, reject) {
        Promise.all([a,b]).then(function(){
            resolve(ret)
        })
    })
}

你可以像这样使用这个函数,这样就可以像往常一样返回一个承诺

multipleAsyncJobs().then(ret=>{
console.log(ret.a)
})

0
投票

我敢于提出另一种选择(带有一些进一步的提示):

export async function promiseAllOfObject(obj) {
  const values = await Promise.all(Object.values(obj));
  return Object.keys(obj).reduce(
    (res, key, index) => (res[key] = values[index], res),
    {}
  );
}

分别将

Promise.all
替换为
Promise.allSettled
即可获得
promiseAllOfObjectSettled()
功能。

而且,作为一个小福利,这里是打字稿版本(替换为

Promise.allSettled
与上面的效果相同):

export async function promiseAllOfObject<
  T extends Record<string, unknown> = Record<string, unknown>,
>(obj: {
  [P in keyof T]: Promise<T[P]>;
}): Promise<T> {
  const values = await Promise.all(Object.values(obj));
  return Object.keys(obj).reduce((res, key, index) => {
    res[key] = values[index];
    return res;
  }, {} as Record<string, unknown>) as T;
}

0
投票

使用 Object.fromEntries(iterable),从 ES10 / ES2019 开始,类似于 这篇文章,但添加了类型:

async function promiseAllOfObject<T extends Object>(obj: T): Promise<{
    [key in keyof T]: Awaited<T[key]>
}> {
    const entries = Object.entries(obj).map(async ([key, value]) => [key, await value])
    return Object.fromEntries(await Promise.all(entries))
}
© www.soinside.com 2019 - 2024. All rights reserved.