javascript - 多个 Javascript 异步进程完成后执行操作

标签 javascript angularjs

因此,我的公司有一个长时间运行的查询状态页面,它显示了不同数据库实例的条形图,这些实例根据长时间运行者的数量和其他条件更改颜色。

问题是,每次调用更新信息时,颜色都会恢复为默认值,并从头开始构建。这是因为我使用 $scope.variable 对象来保存检索 longrunner 数据时的颜色信息。

我想将其切换为在函数内使用本地标准变量,并且只有在检索到所有数据后,才将此变量分配给 $scope.variable。

  • 上下文 - 我们的实例被组织成泳道,因此我为泳道颜色和实例颜色创建一个对象。当所有内容都折叠起来时,您只能看到泳道,因此我需要一种方法让实例颜色向上冒泡到泳道。

所以它相当于这样:

var getLongrunners = function(){

        $scope.longrunnersByInstance = {};

        for (var l = 0; l < $scope.swimlanes.length; l++){
            $scope.slColor[$scope.swimlanes[l].swimlane] = 0;
        }

        for (var j = 0; j < instances.length; j++){
            $scope.longrunnersByInstance[instances[j].instance] = [];
            $scope.instanceColor[instances[j].instance] = 0;

        }



        for (var i = 0; i < instances.length; i++){
            (function(e){
                $http
                    .get('/getLongrunners',{params: {envFlag: '',instance: instances[e].instance}})
                    .then(function(response){
                        var longrunners = response.data;
                        for(var k = 0; k < longrunners.length; k++){
                            $scope.longrunnersByInstance[instances[e].instance].push(longrunners[k]);
                        }

                        if(longrunners.length > $scope.dangerThresh){

                            $scope.instanceColor[instances[e].instance] = 2;

                        }else if(longrunners.length >= $scope.warningThresh){

                            $scope.instanceColor[instances[e].instance] = 1;

                        }

                        if($scope.slColor[instances[e].swimlane] < $scope.instanceColor[instances[e].instance]) {
                            $scope.slColor[instances[e].swimlane] = $scope.instanceColor[instances[e].instance]
                        }
                    },getLongrunnersFail);
            }(i));

所以我希望 $scope.slColor 和 $scope.instanceColor 成为常规局部变量,直到该循环完成。

我研究了 Promise,但这似乎只在调用 .then() 之前对 $http 有用。

有没有一种方法可以制作自定义的 Promise 类型架构并包含多个函数,并且仅在一切完成后才返回 Promise?

谢谢!

编辑:

最近的尝试:

var promises = [];
    var longrunnersByInstance = {};
    var instancesPerf = {};
    var slColor = {};
    var instanceColor = {};

    var promiseTest = function() {

        $scope.longrunnersByInstance = {};

        for (var l = 0; l < $scope.swimlanes.length; l++){
            slColor[$scope.swimlanes[l].swimlane] = 0;
        }

        for (var j = 0; j < instances.length; j++){
            instanceColor[instances[j].instance] = 0;

        }
        instances.forEach(function (instance) {
            promises.push($http
                .get('/getLongrunners', {
                    params: {envFlag: 'bh', instance: instance.instance}
                })
                .then(function (response) {
                    var longrunners = response.data;

                    longrunnersByInstance[instance.instance] = [];

                    for (var k = 0; k < longrunners.length; k++) {
                        longrunnersByInstance[instance.instance].push(longrunners[k]);
                    }

                    if (longrunners.length > $scope.dangerThresh) {

                        instanceColor[instance.instance] = 2;

                    } else if (longrunners.length >= $scope.warningThresh) {

                        instanceColor[instance.instance] = 1;

                    }

                    console.log(instance.instance);

                    if (slColor[instance.swimlane] < instanceColor[instance.instance]) {
                        slColor[instance.swimlane] = instanceColor[instance.instance]
                    }

                    return true;

                }, getLongrunnersFail)
            );

            function getLongrunnersFail(response){
                console.log("getting longrunners failed" + response.status);
            }


            $q.all(promises).then(function () {
                // longrunnersByInstance to $scope

                console.log('calling all promises callback!');

                instances.forEach(function (instance) {
                    $scope.longrunnersByInstance[instance.instance] = longrunnersByInstance[instance.instance];
                });



                // instancesPerf to $scope
                instances.forEach(function (instance) {
                    $scope.instancesPerf[instance.instance] = instancesPerf[instance.instance];
                });

                // slColor to $scope
                instances.forEach(function (instance) {
                    $scope.slColor[instance.instance] = slColor[instance.instance];
                });

                // instanceColor to $scope
                instances.forEach(function (instance) {
                    $scope.instanceColor[instance.instance] = instanceColor[instance.instance];
                });


            }, allPromisesFail);

            function allPromisesFail(){
                console.log("all promises failed")
            }
        });
    };

最佳答案

Angular 使用 $q处理 promise 的服务。

它有一个名为 all 的函数准确处理您遇到的问题类型。

这是一个简单的 fiddle 来演示它:http://jsfiddle.net/ThomasBurleson/QqKuk/

var myApp = angular.module('myApp', []);

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

    var thenFn = function(value){
        console.log('resolved ', value);
        return value;
    },
    q1 = $scope.q1 = $q.defer(),
    q2 = $scope.q2 = $q.defer(),
    p1 = $scope.q1.promise, 
    p2 = $scope.q2.promise;


    $scope.fromThen = $q.all([
                            p1.then(thenFn), 
                            p2.then(thenFn)
                        ])
                        .then(function(values) {        
                            console.log(values);
                            return values;
                        });

    // Must start the AngularJS digest process
    // to allow $q.resolve() to work properly
    // So use $timeOut() or $apply()

    setTimeout(function () {
        $scope.$apply( function() {            
            console.log('resolving delayed promises');
            q1.resolve({value : 1});
            q2.resolve({value : 2});
        });
    }, 100, this);

    /* 
     *  Alternative approach
     *
    $timeout( function() {
        console.log('resolving delayed promises');
        q1.resolve({value : 1});
        q2.resolve({value : 2});        
    });
    */
}

以下是如何将其应用到您的代码中(尚未测试过,所以这只是一个方向,但它应该可以帮助您前进):

var promises = [];
for (var i = 0; i < instances.length; i++){

                //$http return a promise, so you can just push it
                promises.push( $http
                .get('/getLongrunners',{params: {envFlag: '',instance: instances[e].instance}}));

}

$q.all(promises).then(function(values){
   //values should contain an array with all the results you got from all the requests, so you can run through it and aggregate the results
});

关于javascript - 多个 Javascript 异步进程完成后执行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34881256/

相关文章:

angularjs - 如何在 ui-grid angularjs 中启用水平滚动条

javascript - 使用 jQuery 按类访问元素

javascript - JSF 页面中的 $.noConflict() 冲突

javascript - 如何在 JavaScript 的正则表达式中包含内联注释

javascript - AngularJS - 以编程方式检查过滤器是否存在

javascript - 在脚本标签中访问 Angular 变量

javascript - 如何遍历通过 JavaScript 中的扩展运算符传递的参数?

JavaScript 按字母顺序排序不对所有值进行排序

service - AngularJS 中的非单例服务

javascript - 在 Angular 中,我如何在启动前从服务器获取 Bootstrap 数据?