Come ottenere un flusso di controllo non lineare non-dipendente utilizzando Promises (in ES6 lato server)

2

Venendo dal mondo Java, ho problemi a tradurre un approccio multi-thread in IO al concetto di Promesse ES6 di IO aysnc. Molti degli esempi che ho visto sulle promesse mostrano un flusso lineare.

promiseFunction
    .then(functionThatReturnsAnotherPromise)
    .then(functionThatReturnsYetAnotherPromise)
    ...

Gli esempi che mostrano un flusso non lineare mostrano funzioni in cui devo avere tutte le promesse complete prima di passare:

Promise.all([functionThatReturnsOnePromise, functionThatReturnsAnotherPromise])
    .then(functionThatUsesBothReturnValues);

Quello che sto cercando di fare è un flusso di controllo ad albero in cui ogni ramo non ha dipendenza da un altro ramo. Considera questo grafico che mostra il mio flusso di controllo:

  • (1) Crea una richiesta REST asincrona per ottenere i progetti
  • (2) 5 progetti ricevuti. Per ogni progetto ricevuto, (a) creare un'istanza di progetto e (b) effettuare una richiesta REST asincrona per ottenere i team di quel progetto
  • (3-7) x Teams ricevuti. Per ogni squadra ricevuta, (a) creare un'istanza di gruppo, (b) aggiungere la squadra come membro alla sua istanza di progetto padre e (c) effettuare una chiamata REST per ottenere tutti i membri della squadra di quel gruppo
  • (8-21) x membri del team ricevuti. Per ogni membro del team, (a) creare un'istanza del membro del team e (b) aggiungerlo come membro all'istanza del team principale.

Ciò che è importante notare qui è che per far accadere 8-21, 3-7 non tutti devono essere eseguiti. Fondamentalmente, quello che sto cercando di ottenere qui è che una volta ricevuta la risposta di 2, fai 3, 4, 5, 6 e 7. Non appena 3 è finito (non ti preoccupi di 4-7), fai 8-10.

Tuttavia, non sono sicuro di quali costrutti Promise realizzino questo flusso di controllo ad albero, poiché 8-21 non è tutto dipendente dal completamento di 3-7.

getAllProjects()
    .then(function(responseJson) {
        var promises = [];
        for (var index in responseJson.value) {
            var project = new Project(responseJson.value[index]);
            promises.push(getTeamsForProject(project));
        }
        return promises;
    })
    .thenAsEachPromiseCompletes(function(responseJson) {
        var promises = [];
        for (var index in responseJson.value) {
            var team = new Team(responseJson.value[index]);
            promises.push(getTeamMembersForTeam(team));
        }
        return promises;
    })
    .thenAsEachPromiseCompletes(function(responseJson) {
        ...
    });
    
posta Michael Plautz 31.03.2016 - 17:29
fonte

1 risposta

3

Il problema principale sembra essere il punto da ramificare e dove unire le esecuzioni asincrone. Nel tuo codice di esempio stai provando a utilizzare un singolo punto per unire operazioni non dipendenti. Il trucco qui è usare molti rami e join; di avere una serie di progetti e di caricare team. Poi hai una lista di promesse e per ognuna inizierai una nuova filiale e avrai una nuova promessa. Quando incatenato correttamente, le cose iniziano a chiarire e ad apparire più semplici:

getAllProjects().then(function(projects) {
    return Promise.all(projects.map(function (project) {
        return getTeamsForProject(project).then(function (teams) {
            return Promise.all(teams.map(function (team) {
                project.addTeam(team);
                return getTeamMembers(team).then(function (members) {
                    // ...
                });
            }));
        }).then(function () {
            return project;
        });
    }));
}).then(function (projects) {
    // all done
});

Che è un po 'disordinato, ma può sempre essere refactored a qualcosa di più pulito come questo:

getAllProjects().then(function(projects) {
    return Promise.all(projects.map(fetchProjectTeams));
}).then(function (projects) {
    // all done
});

function fetchProjectTeams(project) {
    return getTeamsForProject(project).then(function (teams) {
        return addProjectTeams(teams, project);
    }).then(function () {
        return project;
    });
}

function addProjectTeams(teams, project) {
    return Promise.all(teams.map(function (team) {
        project.addTeam(team);
        return fetchTeamMembers(team);
    }));
}

function fetchTeamMembers(team) {
    return getTeamMembers(team).then(function (members) {
        // ...
    });
}

Ora, nell'ultimo esempio, questa complessa operazione è suddivisa in più fasi comprensibili.

    
risposta data 31.03.2016 - 18:29
fonte

Leggi altre domande sui tag