Best es6 way to get name based results with Promise.all

前端 未结 5 509
陌清茗
陌清茗 2020-12-09 16:30

By default the Promise.All([]) function returns a number based index array that contains the results of each promise.

var promises = [];
promises.push(myFunc         


        
5条回答
  •  独厮守ぢ
    2020-12-09 16:50

    If you don't want to modify the format of result objects, here is a helper function that allows assigning a name to each entry to access it later.

    const allNamed = (nameToPromise) => {
        const entries = Object.entries(nameToPromise);
        return Promise.all(entries.map(e => e[1]))
            .then(results => {
                const nameToResult = {};
                for (let i = 0; i < results.length; ++i) {
                    const name = entries[i][0];
                    nameToResult[name] = results[i];
                }
                return nameToResult;
            });
    };
    

    Usage:

    var lookup = await allNamed({
        rootStatus: fetch('https://stackoverflow.com/').then(rs => rs.status),
        badRouteStatus: fetch('https://stackoverflow.com/badRoute').then(rs => rs.status),
    });
    
    var firstResult = lookup.rootStatus; // = 200
    var secondResult = lookup.badRouteStatus; // = 404
    

    If you are using typescript you can even specify relationship between input keys and results using keyof construct:

    type ThenArg = T extends PromiseLike ? U : T;
    
    export const allNamed = <
        T extends Record>,
        TResolved extends {[P in keyof T]: ThenArg}
    >(nameToPromise: T): Promise => {
        const entries = Object.entries(nameToPromise);
        return Promise.all(entries.map(e => e[1]))
            .then(results => {
                const nameToResult: TResolved = {};
                for (let i = 0; i < results.length; ++i) {
                    const name: keyof T = entries[i][0];
                    nameToResult[name] = results[i];
                }
                return nameToResult;
            });
    };
    

提交回复
热议问题