异步的forEach AngularJS后回调 [英] callback after async forEach AngularJS

查看:1005
本文介绍了异步的forEach AngularJS后回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何添加一个回调函数异步后foreach循环?

下面是一些更好的背景:

  $ scope.getAlbums =功能(用户,回调){
    $ scope.albumsList.forEach(函数(OBJ,I){
        $ scope.getAlbum(用户,obj.id,功能(价值){
            $ scope.albums.push(值);
        });
    });
    // 回电话(); ???
};$ scope.getAlbums('guy123',函数(){
    // forEach循环中全部完成!
    的console.log($ scope.albums)
});

控制器:

  .controller('过滤器',['$范围,Imgur',函数($范围,Imgur){    $ scope.getAlbum =功能(用户ID,回调){
        Imgur.album.get({用户:用户ID:ID},
            功能(值){
                返回回调(value.data);
            }
        );
    }    $ scope.getAlbums =功能(用户,回调){
        //这个foreach循环结束回调函数?
        //请求是异步...
        $ scope.albumsList.forEach(函数(OBJ,I){
            $ scope.getAlbum(用户,obj.id,功能(价值){
                $ scope.albums.push(值);
            });
        });
    };
)]};

服务:

  .factory('Imgur',函数($资源){
    返回{
        专辑:$资源('https://api.imgur.com/3/account/:user/album/:id')
    }
});


解决方案

安德鲁说 $ Q 的使用和递延对象应该让你实现你的目标。

您想要使用 $ q.all()这将确保所有你的诺言对象的都解决了,然后你可以叫你回电。然后()

 函数MyCtrl($范围,$ Q $ HTTP){    $ scope.albumsList = [{
            ID:1,
            名称:11
        },{
            ID:2,
            名称:22
        }
    ];
    $ scope.albums = [];
    $ scope.getAlbum =功能(用户ID,回调){
        返回$ http.get(https://api.imgur.com/3/account/+用户+/专辑/+ ID).success(
            功能(值){
                返回回调(value.data);
            }
        );
    }
    $ scope.getAlbums =功能(用户,回调){
        VAR舞会= [];
        $ scope.albumsList.forEach(函数(OBJ,I){
            prom.push($ scope.getAlbum(用户,obj.id,功能(价值){
                $ scope.albums.push(值);
            }));
        });
        $ q.all(PROM)。然后(函数(){
            回电话();
        });
    };
    $ scope.getAlbums('guy123',函数(){
        警报($ scope.albums.length);
    });
}

实例上的jsfiddle

作品,但不与 $ HTTP 要求

通过递延对象,你获得对一个承诺,你可以改变连续访问则()通话在一起。当您解决延迟对象它将执行的foreach,然后执行您的回调您所提供的功能。我尝试了一下进一步简化你的榜样,所以它会在工作的jsfiddle

 函数MyCtrl($范围,$ HTTP,$ Q){    $ scope.albumsList = [{
        ID:1,
        名称:11
    },{
        ID:2,
        名称:22
    }];
    $ scope.albums = [];
    $ scope.getAlbums =功能(用户,回调){
        变种推迟= $ q.defer();
        VAR承诺= deferred.promise;
        promise.then(函数(){
            $ scope.albumsList.forEach(函数(OBJ,I){
                $ scope.albums.push(OBJ);
            });
        })。然后(函数(){
            回电话();
        });
        deferred.resolve();
    };
    $ scope.getAlbums('guy123',函数(){
        警报($ scope.albums.length);
    });
}

实例上的jsfiddle

延期并承诺多一点读书。

How do I add a callback function after an async forEach Loop?

Here is some better context:

$scope.getAlbums = function(user, callback) {
    $scope.albumsList.forEach(function (obj, i) {
        $scope.getAlbum(user, obj.id, function(value){
            $scope.albums.push(value);
        });
    });
    // callback(); ???
};

$scope.getAlbums('guy123', function(){
    // forEach loop is all done!
    console.log($scope.albums)
});

Controller:

.controller('Filters', ['$scope','Imgur', function($scope, Imgur) {

    $scope.getAlbum = function(user, id, callback) {
        Imgur.album.get({user:user, id:id},    
            function(value) {
                return callback(value.data);
            }
        );
    }

    $scope.getAlbums = function(user, callback) {
        // Callback function at end of this forEach loop?
        // Request is async...
        $scope.albumsList.forEach(function (obj, i) {
            $scope.getAlbum(user, obj.id, function(value){
                $scope.albums.push(value);
            });
        });
    };
)]};

Service:

.factory('Imgur', function($resource) {
    return {
        album : $resource('https://api.imgur.com/3/account/:user/album/:id')
    }
});

解决方案

As Andrew said usage of $q and the deferred object should allow you to accomplish your goal.

You want to use $q.all() This will make sure all of your promise objects are resolved and then you can call your call back in .then()

function MyCtrl($scope, $q, $http) {

    $scope.albumsList = [{
            id: 1,
            name: "11"
        }, {
            id: 2,
            name: "22"
        }
    ];
    $scope.albums = [];
    $scope.getAlbum = function(user, id, callback) {
        return $http.get("https://api.imgur.com/3/account/" + user + "/album/" + id).success(
            function(value) {
                return callback(value.data);
            }
        );
    }
    $scope.getAlbums = function (user, callback) {
        var prom = [];
        $scope.albumsList.forEach(function (obj, i) {
            prom.push($scope.getAlbum(user, obj.id, function(value){
                $scope.albums.push(value);
            }));
        });
        $q.all(prom).then(function () {
            callback();
        });
    };
    $scope.getAlbums('guy123', function () {
        alert($scope.albums.length);
    });
}

Example with this on jsfiddle

Works but not with $http calls

With the deferred object you gain access to a promise where you can change successive then() calls together. When you resolve the deferred object it will execute the foreach and then execute your call back function you supplied. I tried to simplify your example a bit further so it would work in jsfiddle.

function MyCtrl($scope, $http, $q) {

    $scope.albumsList = [{
        id: 1,
        name: "11"
    }, {
        id: 2,
        name: "22"
    }];
    $scope.albums = [];
    $scope.getAlbums = function (user, callback) {
        var deferred = $q.defer();
        var promise = deferred.promise;
        promise.then(function () {
            $scope.albumsList.forEach(function (obj, i) {
                $scope.albums.push(obj);
            });
        }).then(function () {
            callback();
        });
        deferred.resolve();
    };
    $scope.getAlbums('guy123', function () {
        alert($scope.albums.length);
    });
}

Example on jsfiddle

A bit more reading on deferred and promises.

这篇关于异步的forEach AngularJS后回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆