相当于BlueBird Promise.props的ES6承诺?

时间:2017-06-17 04:29:30

标签: javascript node.js promise bluebird es6-promise

我想等到Promise完成一个字的地图。 BlueBird有Promise.props来完成这个,但有一个干净的方法在常规的JavaScript中执行此操作吗?我想我可以创建一个包含单词和Promise的新对象,获取这些对象的Promise数组,然后调用Promise.all并将它们放在地图中,但它看起来有点过分。

9 个答案:

答案 0 :(得分:1)

如果您正在使用承诺值(或承诺和非承诺的混合)处理Map,并且您希望最终解析的值为Map并且所有值都已解析

const mapPromise = map => 
    Promise.all(Array.from(map.entries()).map(([key, value]) => Promise.resolve(value).then(value => ({key, value}))))
    .then(results => {
        const ret = new Map();
        results.forEach(({key, value}) => ret.set(key, value));
        return ret;
    });

虽然,我打赌有人有一个更为明智的方式来做这件事,一些新的ES2015 +的东西对我来说还是新的:p

答案 1 :(得分:1)

将ES6 + Object.entries()和Object.fromEntries()组合在一起的替代实现:

async function pprops(input) {
    return Object.fromEntries(
        await Promise.all(
            Object.entries(input)
                .map(
                    ([k, p])=>p.then(v=>[k, v])
                )
        )
    );
};

答案 2 :(得分:0)

建议使用像bluebird这样的库。如果你真的想自己这样做,主要的想法是:

  • 解析每个地图值,并将承诺的值与相应的键
  • 连接起来
  • 将这些承诺传递给Promise.all
  • 将最终承诺的数组转换回Map

我会使用Array.from的第二个参数,以及可以将键/值对数组传递给Map构造函数的事实:



Promise.allMap = function(map) {
    return Promise.all( Array.from(map, 
        ([key, promise]) => Promise.resolve(promise).then(value => [key, value])
    ) ).then( results => new Map(results));
}

// Example data
const map = new Map([
    ["Planet", Promise.resolve("Earth")],
    ["Star", Promise.resolve("Sun")],
    ["Galaxy", Promise.resolve("Milky Way")],
    ["Galaxy Group", Promise.resolve("Local Group")]
]);

// Resolve map values
Promise.allMap(map).then( result => console.log([...result]) );

.as-console-wrapper { max-height: 100% !important; top: 0; }




答案 3 :(得分:0)

以下是适用于普通对象的简单实现,因此

makePromiseFromObject({a: Promise.resolve(1)})是一个以{a: 1}解析的承诺。

const makePromiseFromObject = (obj) => {
  const keys = Object.keys(obj)
  const values = Object.values(obj)
  return Promise.all(values)
    .then(resolved => {
      const res = {}
      for (let i = 0; i < keys.length; i += 1) res[keys[i]] = resolved[i]
      return res
    })
}

答案 4 :(得分:0)

如果您使用ramda,则可以这样做:

export const promiseProps: <T>(obj: {[x: string]: Promise<T>}) => Promise<{[x: string]: T}> =
 (obj) => Promise.all(R.values(obj)).then(R.zipObj(R.keys(obj)));

答案 5 :(得分:0)

您只需使用Promise.all + reduce即可编写

const promiseProps = (props) => Promise.all(Object.values(props)).then(
      (values) => Object.keys(props).reduce((acc, prop, index) => {
         acc[prop] = values[index];
         return acc;
      }, {})
    );

答案 6 :(得分:0)

古老的async.js库有一个对应的约定:async-q

承诺的async-q库支持async库中的所有功能。具体是async.parallel()。乍一看,async.parallel()就像Promise.all()接受一组函数(注意一个区别,就是一组 function ,而不是 promises ),并且并行运行它们。 async.parallel之所以与众不同之处在于它还接受一个对象:

const asyncq = require('async-q');

async function foo () {
    const results = await asyncq.parallel({
        something: asyncFunction,
        somethingElse: () => anotherAsyncFunction('some argument')
    });

    console.log(results.something);
    console.log(results.somethingElse);
}

答案 7 :(得分:0)

还有一个不错的lodash变体,用于完整的js对象。

async function makePromiseFromObject(obj: {[key: string]: Promise<any>}) {
    return _.zipObject(Object.keys(obj), await Promise.all(Object.values(obj)))
}    

答案 8 :(得分:0)

我有两种不同的使用 ES6 异步函数的实现:

async function PromiseAllProps(object) {
    const values = await Promise.all(Object.values(object));
    Object.keys(object).forEach((key, i) => object[key] = values[i]);
    return object;
}

一行更短,但优化程度较低:

async function PromiseAllProps(object) {
    const values = await Promise.all(Object.values(object));
    return Object.fromEntries(Object.keys(object).map((prop, i) => ([prop, values[i]])));
}

示例

const info = await PromiseAllProps({
    name: fetch('/name'),
    phone: fetch('/phone'),
    text: fetch('/foo'),
});

console.log(info);
{
    name: "John Appleseed",
    phone: "5551234",
    text: "Hello World"
}