Pertanyaan angular $ q, Cara menukar banyak janji dalam dan setelah pengulangan


Saya ingin memiliki for-loop yang menyebut async fungsi setiap iterasi.

Setelah for-loop saya ingin mengeksekusi blok kode lain, tetapi tidak sebelum semua panggilan sebelumnya di for-loop telah diselesaikan.

Masalah saya saat ini adalah, bahwa blok kode setelah for-loop dijalankan sebelum semua panggilan async selesai atau tidak dijalankan sama sekali.

Bagian kode dengan FOR-loop dan blok kode setelahnya (untuk kode lengkap, silakan lihat biola):

[..]
function outerFunction($q, $scope) {
    var defer = $q.defer();    
    readSome($q,$scope).then(function() {
        var promise = writeSome($q, $scope.testArray[0])
        for (var i=1; i < $scope.testArray.length; i++) {
             promise = promise.then(
                 angular.bind(null, writeSome, $q, $scope.testArray[i])
             );                                  
        } 
        // this must not be called before all calls in for-loop have finished
        promise = promise.then(function() {
            return writeSome($q, "finish").then(function() {
                console.log("resolve");
                // resolving here after everything has been done, yey!
                defer.resolve();
            });   
        });        
    });   

    return defer.promise;
}

Saya telah membuat jsFiddle yang dapat ditemukan di sini http://jsfiddle.net/riemersebastian/B43u6/3/.

Saat ini sepertinya perintah eksekusi baik-baik saja (lihat keluaran konsol).

Tebakan saya adalah, bahwa ini hanya karena setiap panggilan fungsi kembali segera tanpa melakukan pekerjaan nyata. Saya telah mencoba menunda penangguhan.menyelesaikan dengan setTimeout tetapi gagal (yaitu blok kode terakhir tidak pernah dijalankan). Anda bisa melihatnya di blok yang sudah ketinggalan di dalam biola.

Ketika saya menggunakan fungsi nyata yang menulis ke file dan membaca dari file, blok kode terakhir dijalankan sebelum operasi penulisan terakhir selesai, yang bukan yang saya inginkan.

Tentu saja, kesalahan bisa berada di salah satu fungsi baca / tulis, tetapi saya ingin memverifikasi bahwa tidak ada yang salah dengan kode yang saya posting di sini.


75
2018-01-09 15:31


asal


Jawaban:


Yang perlu Anda gunakan adalah $ q.all yang menggabungkan sejumlah janji menjadi satu yang hanya diselesaikan ketika semua janji diselesaikan.

Dalam kasus Anda, Anda dapat melakukan sesuatu seperti:

function outerFunction() {

    var defer = $q.defer();
    var promises = [];

    function lastTask(){
        writeSome('finish').then( function(){
            defer.resolve();
        });
    }

    angular.forEach( $scope.testArray, function(value){
        promises.push(writeSome(value));
    });

    $q.all(promises).then(lastTask);

    return defer.promise;
}

118
2018-01-10 23:28



Dengan ES7 baru Anda dapat memiliki hasil yang sama dengan cara yang jauh lebih mudah:

let promises =  angular.forEach( $scope.testArray, function(value){
    writeSome(value);
});

let results = await Promise.all(promises);

console.log(results);

2
2018-06-01 08:29



Kamu dapat memakai $q dan 'mengurangi' bersama-sama, untuk memenuhi janji-janji itu.

function setAutoJoin() {
    var deferred = $q.defer(), data;
    var array = _.map(data, function(g){
            return g.id;
        });

    function waitTillAllCalls(arr) {
        return arr.reduce(function(deferred, email) {
            return somePromisingFnWhichReturnsDeferredPromise(email);
        }, deferred.resolve('done'));
    }

    waitTillAllCalls(array);

    return deferred.promise;
}

0
2018-04-21 13:12



Ini bekerja untuk saya menggunakan sintaks ES5

function outerFunction(bookings) {

    var allDeferred = $q.defer();
    var promises = [];

    lodash.map(bookings, function(booking) {
        var deferred = $q.defer();

        var query = {
            _id: booking.product[0].id,
            populate: true
        }

        Stamplay.Object("product").get(query)
        .then(function(res) {
            booking.product[0] = res.data[0];
            deferred.resolve(booking)
        })
        .catch(function(err) {
            console.error(err);
            deferred.reject(err);
        });

        promises.push(deferred.promise);
    });

    $q.all(promises)
    .then(function(results) { allDeferred.resolve(results) })
    .catch(function(err) { allDeferred.reject(results) });

    return allDeferred.promise;
}

0
2017-11-04 01:04