Equivalent of BlueBird Promise.props for ES6 Promises?

匆匆过客 提交于 2019-12-22 04:49:19

问题


I would like to wait for a map of word to Promise to finish. BlueBird has Promise.props which accomplishes this, but is there a clean way to do this in regular javascript? I think I can make a new object which houses both the word and the Promise, get an array of Promises of those objects, and then call Promise.all and put them in the map, but it seems like overkill.


回答1:


If you are dealing with a Map with values that are promises (or a mix of promises and non-promises) - and you want the final resolved value to be a Map with all values resolved

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;
    });

Although, I bet someone has a slicker way to do this, some of the new ES2015+ stuff is still new to me :p




回答2:


It would be advisable to use a library like bluebird for this. If you really want to do this yourself, the main idea is to:

  • Resolve each of the map values and connect the promised value back with the corresponding key
  • Pass those promises to Promise.all
  • Convert the final promised array back to a Map

I would make use of the second argument of Array.from, and the fact that an array of key/value pairs can be passed to the Map constructor:

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:


The following is a simple implementation that works on plain objects, so that

makePromiseFromObject({a: Promise.resolve(1)}) is a Promise that resolves with {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:


if you use ramda you can do it like so:

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:


You can simply write it using 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:


The venerable async.js library has a promisified counterpart: async-q

The promisified async-q library supports all the functions in the async library. Specifically async.parallel(). At first glance async.parallel() looks just like Promise.all() in accepting an array of functions (note one difference, an array of functions, not promises) and run them in parallel. What makes async.parallel special is that it also accepts an object:

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);
}


来源:https://stackoverflow.com/questions/44600771/equivalent-of-bluebird-promise-props-for-es6-promises

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!