web-dev-qa-db-fra.com

Lodash: est-il possible d'utiliser des cartes avec des fonctions asynchrones?

Considérons ce code

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

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

Ce que addEnabledProperty fait est d'étendre l'objet en ajoutant une propriété enabled, mais ce n'est pas important. La fonction elle-même fonctionne bien

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

Existe-t-il un moyen d'utiliser _.map (ou un autre système), de parcourir en boucle le tableau responseJson entier pour utiliser addEnabledProperty contre chaque élément?

J'ai essayé:

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

Mais comme il n’est pas asynchrone, il gèle l’application.

J'ai essayé:

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

Mais j’ai eu une erreur js (à propos de la rangée return await addEnabledProperty(chanell);)

attendre est un mot réservé 

Puis essayé

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

Mais j'ai un tableau de promesses ... et je ne comprends pas pourquoi ...

Quoi d'autre!??

EDIT: Je comprends vos griefs car je n’ai pas précisé que addEnabledProperty() renvoie une Promise, mais je ne le savais vraiment pas. En fait, j'ai écrit "J'ai reçu un tableau de promesses ... et je ne comprends pas pourquoi"

9
realtebo

Pour traiter vos réponses en parallèle, vous pouvez utiliser Promise.all:

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

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

Étant donné que la méthode addEnabledProperty est async, les éléments suivants devraient également fonctionner (par @CRice):

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

Pourquoi ne pas utiliser partial.js ( https://github.com/marpple/partial.js )

Il couvre à la fois la promesse et le modèle normal par le même code.

_p.map([1, 2, 3], async (v) => await setTimeout(console.log(v), 1000);
0
Juneho Nam

Vous pouvez utiliser Promise.all() pour exécuter toutes les promesses de votre tableau.

responseJson = await Promise.all(_.map(responseJson, async function(channel) {
        return await addEnabledProperty(channell);
    }));
0
Rodrigo Leite

J'ai constaté que je n'avais pas à mettre l'async/wait à l'intérieur du wrapper Promise.all

L'utilisation de cette connaissance, associée à la chaîne lodash (_.chain), pourrait permettre d'obtenir la version simplifiée suivante de la réponse acceptée: 

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