web-dev-qa-db-ger.com

Angularjs $ q.all

Ich habe $ q.all in anglejs implementiert, kann den Code jedoch nicht zum Laufen bringen. Hier ist mein Code:

UploadService.uploadQuestion = function(questions){

        var promises = [];

        for(var i = 0 ; i < questions.length ; i++){

            var deffered  = $q.defer();
            var question  = questions[i]; 

            $http({

                url   : 'upload/question',
                method: 'POST',
                data  : question
            }).
            success(function(data){
                deffered.resolve(data);
            }).
            error(function(error){
                deffered.reject();
            });

            promises.Push(deffered.promise);
        }

        return $q.all(promises);
    }

Und hier ist mein Controller, der die Dienste aufruft:

uploadService.uploadQuestion(questions).then(function(datas){

   //the datas can not be retrieved although the server has responded    
}, 
function(errors){ 
   //errors can not be retrieved also

})

Ich denke, es gibt ein Problem beim Einrichten von $ q.all in meinem Dienst.

104
themyth92

In Javascript gibt es keine block-level scopes nur function-level scopes:

Lesen Sie diesen Artikel über JavaScript Scoping and Hoisting .

Sehen Sie, wie ich Ihren Code getestet habe:

var deferred = $q.defer();
deferred.count = i;

console.log(deferred.count); // 0,1,2,3,4,5 --< all deferred objects

// some code

.success(function(data){
   console.log(deferred.count); // 5,5,5,5,5,5 --< only the last deferred object
   deferred.resolve(data);
})
  • Wenn Sie var deferred= $q.defer(); in eine for-Schleife schreiben, wird sie an den Anfang der Funktion gesetzt . Dies bedeutet, dass Javascript diese Variable in der deklariert Funktionsumfang außerhalb des for loop.
  • Bei jeder Schleife überschreibt die letzte verzögert die vorherige, es gibt keinen Bereich auf Blockebene, in dem eine Referenz auf dieses Objekt gespeichert werden kann.
  • Wenn asynchrone Rückrufe (Erfolg/Fehler) aufgerufen werden, verweisen sie nur auf das letzte zurückgestellte Objekt und nur es wird aufgelöst, also $ q.all wird niemals aufgelöst , da es immer noch auf andere zurückgestellte Objekte wartet.
  • Sie müssen für jedes Element, das Sie iterieren, eine anonyme Funktion erstellen.
  • Da Funktionen Gültigkeitsbereiche haben, bleibt der Verweis auf die zurückgestellten Objekte auch nach Ausführung von Funktionen in einem closure scope erhalten.
  • Wie #dfsq kommentierte: Es ist nicht erforderlich, ein neues zurückgestelltes Objekt manuell zu erstellen, da $ http selbst ein Versprechen zurückgibt.

Lösung mit angular.forEach:

Hier ist ein Demo-Plunker: http://plnkr.co/edit/NGMp4ycmaCqVOmgohN53?p=preview

UploadService.uploadQuestion = function(questions){

    var promises = [];

    angular.forEach(questions , function(question) {

        var promise = $http({
            url   : 'upload/question',
            method: 'POST',
            data  : question
        });

        promises.Push(promise);

    });

    return $q.all(promises);
}

Am liebsten benutze ich Array#map:

Hier ist ein Demo-Plunker: http://plnkr.co/edit/KYeTWUyxJR4mlU77svw9?p=preview

UploadService.uploadQuestion = function(questions){

    var promises = questions.map(function(question) {

        return $http({
            url   : 'upload/question',
            method: 'POST',
            data  : question
        });

    });

    return $q.all(promises);
}
222
Ilan Frumer

$ http ist auch ein Versprechen, Sie können es einfacher machen:

return $q.all(tasks.map(function(d){
        return $http.post('upload/tasks',d).then(someProcessCallback, onErrorCallback);
    }));
35
Zerkotin

Das Problem scheint zu sein, dass Sie den deffered.promise Hinzufügen, wenn deffered selbst das Versprechen ist, das Sie hinzufügen sollten:

Versuchen Sie, zu promises.Push(deffered); zu wechseln, damit Sie dem Array nicht das unverpackte Versprechen hinzufügen.

 UploadService.uploadQuestion = function(questions){

            var promises = [];

            for(var i = 0 ; i < questions.length ; i++){

                var deffered  = $q.defer();
                var question  = questions[i]; 

                $http({

                    url   : 'upload/question',
                    method: 'POST',
                    data  : question
                }).
                success(function(data){
                    deffered.resolve(data);
                }).
                error(function(error){
                    deffered.reject();
                });

                promises.Push(deffered);
            }

            return $q.all(promises);
        }
12
Davin Tryon