javascript when AngularJS: promesse concatenate



q when promise (1)

Seguendo i suggerimenti della convalida e delle promesse di AngularJS , vorrei concatenare le finestre di conferma e quindi convalidare più passaggi contemporaneamente.

Sulla base dei dati forniti dall'utente, viene effettuata una chiamata API per vedere ciò che deve essere confermato dall'utente. Per ogni passaggio che richiede conferma, chiedere all'utente e lasciare che decidano se andare al passaggio successivo. Se qualsiasi passo restituisce false, l'intera catena dovrebbe restituire false.

Ho letto molto su JS asincrona e promesse, ma devo ammettere che sono ancora abbastanza nuovo in questo. Come incatenarli correttamente per ottenere un finale vero / falso per tutti i passaggi? Si noti che è necessaria una chiamata API per determinare ciò che tutti devono essere mostrati all'utente in base alle informazioni fornite, quindi fetchSomeData () come prima chiamata nella catena.

Qualsiasi aiuto o suggerimento sarà molto apprezzato.

fetchSomeData = function() {
    var deferred = $q.defer();
    api.fetchData(param1, param2, param3)
        .then(function(data) {
        deferred.resolve(data.content);
    }, api.errorHandler);
    return deferred.promise;
}
// data = {condition1: false, condition2: true, condition3: true}
// display confirmation dialogs for step 2 and step 3, not step 1 

confirmStep1 = function(data) {
    if (data.condition1) {
        return confirmDialogService.popConfirm('step1').then(function(confirmed) {
            return confirmed;
        }, function() {
            return false;
        });
    } else {
        return $q.when(true);
    }
}

confirmStep2 = function(data) {
    if (data.condition2) {
        return confirmDialogService.popConfirm('step2').then(function(confirmed) {
            return confirmed;
        }, function() {
            return false;
        });
    } else {
        return $q.when(true);
    }
}

confirmStep3 = function(data) {
    if (data.condition3) {
        return confirmDialogService.popConfirm('step3').then(function(confirmed) {
            return confirmed;
        }, function() {
            return false;
        });
    } else {
        return $q.when(true);
    }
}

confirmSteps = function() {
    return fetchSomeData()
        .then(confirmStep1(data))
        .then(confirmStep2(data))
        .then(confirmStep3(data));
}

confirmSteps().then(function(allConfirmed) {
    if (allConfirmed == true) {
        doSomething();
    } else {
        return;
    }
});

dfsq ha iniziato a scrivere una risposta ma ha cancellato il suo così con la sua benedizione sto aggiungendo la mia opinione su di esso:

confirmSteps = function() {
    return fetchSomeData()
        .then(confirmStep1(data))
        .then(confirmStep2(data))
        .then(confirmStep3(data));
}

Questo chiama le funzioni, è uguale a setTimeout(alert("Hi"),5) non vuoi chiamare le funzioni che vuoi concatenarle. Come setTimeout(function(){ alert("Hi"); }, 5) ;

confirmSteps = function() {
    return fetchSomeData()
        .then(confirmStep1)
        .then(confirmStep2)
        .then(confirmStep3);
}

Tuttavia, questo passerebbe i data alla prima promessa e il risultato della precedente promessa a quella successiva, invece si desidera passare i data a tutti e tre, è possibile farlo eliminando un livello:

confirmSteps = function() {
    return fetchSomeData().then(function(data){
        var v1, v2;
        return confirmStep1(data).then(function(d){ 
           v1 = d;
           return confirmStep2(data);
        }).then(function(d){
           v2 = d;
           return confirmStep3(data);
        }).then(function(v3){
            return v1 && v2 && v3;
        })
    });
};

Funziona ma è piuttosto crufty, invece puoi usare il cortocircuito - un po 'come come && valuta il lato sinistro solo se è falso. Inoltre possiamo gestire tutti gli errori in una posizione centrale. Questo renderebbe il tuo codice simile.

confirmStep1 = function(data) {
    if (data.condition1) return $q.when(true);
    return confirmDialogService.popConfirm('step1');
};

confirmStep2 = function(data) {
    if (data.condition2) return $q.when(true);
    return confirmDialogService.popConfirm('step2');
};

confirmStep3 = function(data) {
    if (data.condition3) return $q.when(true);
    return confirmDialogService.popConfirm('step3'):
};

confirmSteps = function() {
    var data = fetchSomeData();
    return data.then(confirmStep1).then(function(soFar){ 
         if(!soFar) return false; 
         return data.then(confirmStep2); 
    }).then(function(soFar){ 
         if(!soFar) return false; 
         return data.then(confirmStep3); 
    }).catch(function(){ return false; });
};

Come un consiglio in più questo:

fetchSomeData = function() {
    var deferred = $q.defer();
    api.fetchData(param1, param2, param3)
        .then(function(data) {
        deferred.resolve(data.content);
    }, api.errorHandler);
    return deferred.promise;
};

Può semplicemente diventare:

fetchSomeData = function() {
    return api.fetchData(param1, param2, param3).then(function(data) {
        return data.content;
    }, api.errorHandler);
};




angular-promise