Lodash: is it possible to use map with async functions?

旧城冷巷雨未停 提交于 2019-12-05 15:02:42

问题


Consider this code

const response  = await fetch('<my url>');
const responseJson = await response.json();
responseJson =  _.sortBy(responseJson, "number");

responseJson[0] = await addEnabledProperty(responseJson[0]);

What addEnabledProperty does is to extend the object adding an enabled property, but this is not important. The function itself works well

async function addEnabledProperty (channel){

    const channelId = channel.id;
    const stored_status = await AsyncStorage.getItem(`ChannelIsEnabled:${channelId}`);
    let boolean_status = false;
    if (stored_status == null) {
        boolean_status = true;
    } else {
        boolean_status = (stored_status == 'true');
    }

    return _.extend({}, channel, { enabled: boolean_status });
}

Is there a way to use _.map (or another system), to loop trough entire responseJson array to use addEnabledProperty against each element?

I tried:

responseJson = _.map(responseJson,  function(channel) {
            return addEnabledProperty(channell);
        });

But it's not using async so it freeze the app.

I tried:

responseJson = _.map(responseJson,  function(channel) {
            return await addEnabledProperty(chanell);
        });

But i got a js error (about the row return await addEnabledProperty(chanell);)

await is a reserved word

Then tried

responseJson = _.map(responseJson, async function(channel) {
            return await addEnabledProperty(channell);
        });

But I got an array of Promises... and I don't understand why...

What else!??

EDIT: I understand your complains about I didn't specify that addEnabledProperty() returns a Promise, but, really, I didn't know it. In fact, I wrote "I got an array of Promises... and I don't understand why "


回答1:


To process your response jsons in parallel you may use Promise.all:

const responseJson = await response.json();
responseJson = _.sortBy(responseJson, "number");

let result = await Promise.all(_.map(responseJson, async (json) => 
  await addEnabledProperty(json))
);

Since addEnabledProperty method is async, the following also should work (per @CRice):

let result = await Promise.all(_.map(responseJson, addEnabledProperty));



回答2:


I found that I didn't have to put the async / await inside of the Promise.all wrapper.

Using that knowledge, in conjunction with lodash chain (_.chain) could result in the following simplified version of the accepted answer:

const responseJson = await Promise.all( _
                       .chain( response.json() )
                       .sortBy( 'number' )
                       .map( json => addEnabledProperty( json ) )
                       .value()
                     )



回答3:


How about using partial.js(https://github.com/marpple/partial.js)

It cover both promise and normal pattern by same code.

_p.map([1, 2, 3], async (v) => await promiseFunction());



回答4:


You can use Promise.all() to run all the promises in your array.

responseJson = await Promise.all(_.map(responseJson, (channel) => {
        return addEnabledProperty(channel);
    }));


来源:https://stackoverflow.com/questions/47065444/lodash-is-it-possible-to-use-map-with-async-functions

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