programing

angular $q, for-loop 내 및 후에 여러 약속을 연결하는 방법

goodsources 2023. 2. 25. 20:56
반응형

angular $q, for-loop 내 및 후에 여러 약속을 연결하는 방법

반복할 때마다 비동기 함수를 호출하는 for-loop을 원합니다.

for-loop 후에 다른 코드블록을 실행하고 싶은데 for-loop 내의 이전 콜이 모두 해결될 때까지는 실행하지 않습니다.

현시점에서의 문제는 for-loop 후의 코드 블록이 모든 비동기 콜이 종료되기 전에 실행되거나 전혀 실행되지 않는 것입니다.

FOR-루프가 있는 코드 부분과 그 뒤의 코드 블록(전체 코드는 바이올린 참조):

[..]
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;
}

jsFiddle을 작성했습니다.이거는 http://jsfiddle.net/riemersebastian/B43u6/3/에 있습니다.

현시점에서는 실행 순서는 정상인 것 같습니다(콘솔 출력 참조).

이는 단순히 모든 함수 호출이 실제 작업을 수행하지 않고 즉시 반환되기 때문이라고 추측합니다.setTimeout을 사용하여 defer.resolve를 지연시키려고 했지만 실패했습니다(마지막 코드 블록은 실행되지 않았습니다).바이올린의 외설 블록에서 볼 수 있습니다.

파일에 쓰고 파일에서 읽는 실제 기능을 사용하면 마지막 쓰기 작업이 끝나기 전에 마지막 코드 블록이 실행되는데, 이것은 내가 원하는 것이 아니다.

물론 읽기/쓰기 기능 중 하나일 수도 있지만, 여기에 게재한 코드에 이상이 없음을 확인하고 싶습니다.

필요한 것은 $q.입니다.이것은 많은 약속을 하나로 묶은 것입니다.이것은 모든 약속이 해결되었을 때만 해결됩니다.

이 경우 다음과 같은 작업을 수행할 수 있습니다.

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

새로운 ES7을 사용하면 훨씬 더 간단한 방법으로 동일한 결과를 얻을 수 있습니다.

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

let results = await Promise.all(promises);

console.log(results);

사용할 수 있습니다.$q그리고 약속을 묶기 위해 함께 '연결'을 합니다.

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

이것은 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;
}

언급URL : https://stackoverflow.com/questions/21024411/angular-q-how-to-chain-multiple-promises-within-and-after-a-for-loop

반응형