关于javascript:AngularJSPromise$ q.all和SignalR

AngularJS Promises $q.all and SignalR

我检查了有关诺言的答案,但是我无法使我的代码正常工作(也许我在其他地方做错了什么大事)

通常,我正在使用AngularJS和SignalR进行小型测试应用程序。我有如下所示的signalR服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
(function () {
'use strict';

var serviceId = 'signalRSvc';
angular.module('app').service(serviceId, ['$rootScope', signalrcontext]);

function signalrcontext( $rootScope) {
    var performanceHub = null;
    var connection = null;        

    var service = {
        initialize: initialize,
        getPerformanceCounters: getPerformanceCounters,
        getAllValues: getAllValues
    };

    return service;

    function initialize() {
        connection = $.connection;

        performanceHub = connection.webServicePerformanceHub;
        connection.hub.logging = true;

        performanceHub.client.updatePerformanceData = function(performanceData) {
            $rootScope.$emit("updatePerformanceData", performanceData);
        };

        return connection.hub.start();
    };

    function getPerformanceCounters() {
        return performanceHub.server.getPerformanceCounters();
    };

    function getAllValues(id) {
        return performanceHub.server.getAllValues(id);
    };
}
})();

我要做的是初始化SignalR,然后执行getPerformanceCounters()方法,该方法将下载要呈现的计数器列表(以对象数组形式返回),然后为每个计数器获取数据,并且问题开始了。根据MS文档,SignalR代理方法正在返回Promise。我已经编写了这段代码,但我不知道为什么它不能在步骤getAllValues上工作(根据此答案,AngularJS Promises,$ q,推迟它应该可以工作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   function initSignalR() {
        return signalRSvc.initialize().then(function() {                
            return signalRSvc.getPerformanceCounters();
        }).then(function(configurations) {
            log('performance counters configuration downloaded');
            return getAllValues(configurations);
        }).then(function (resultData) {
            vm.resultData = resultData;
        });
    }

    function getAllValues(configurations) {
        var promises = new Array();

        angular.forEach(configurations, function(configuration) {
            promises.push(signalRSvc.getAllValues(configuration.Id));
        });

        return $q.all(promises);
    }

据我所知,最后一次应该在对signalRSvc.getAllValues的所有"调用"完成后执行,并且resultData应该包含从那些Promise返回的对象数组。取而代之的是,我得到了一些甚至不是数组的垃圾。

令人惊讶的(当然对我来说),当我做这样的事情

1
2
3
4
5
6
7
8
9
10
11
    function getAllValues(configurations) {
        var promises = new Array();

        angular.forEach(configurations, function(configuration) {
            promises.push(signalRSvc.getAllValues(configuration.Id));
        });

        return $q.all(promises).then(function(resultData) {  
           //here result data is fine!!
        });
    }

嵌套则结果数据就很好了(但是,解决Promise的顺序就搞砸了)。

由于我没主意,请多多帮助。


我的朋友Yan Yankowski为AngularJS编写了一个很棒的SignalRpackage器。您可以从GitHub下载它,
该package器还使用$ q promises获得结果。

示例:

1
hubFactory.getHub("myHub").run("myMethod", param_1, param_2, .... param_n).then ( function(responseData) {} )


问题似乎与SingalR返回的Promise有关(我的团队同事发现了这一点)。 SignalR返回的jQuery Promise在所有情况下均与AngularJS Promise不兼容。解决方案是用$ q.whenpackage来自signalR代理的方法。现在一切正常。

固定代码(仍然包含与SignalR相关的其他问题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.....

return service;

function initialize() {
    connection = $.connection;

    performanceHub = connection.webServicePerformanceHub;
    connection.hub.logging = true;

    performanceHub.client.updatePerformanceData = function(performanceData) {
        $rootScope.$emit("updatePerformanceData", performanceData);
    };

    return $q.when(connection.hub.start();
};

function getPerformanceCounters() {
    return $q.when(performanceHub.server.getPerformanceCounters());
};

function getAllValues(id) {
    return $q.when(performanceHub.server.getAllValues(id));
};
.....

以前无法运行的Promise链现在可以正常运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function initSignalR() {
    return signalRSvc.initialize().then(function () {
        return signalRSvc.getPerformanceCounters();
    }).then(function (configurations) {
        chartConfigurations = configurations;                
        return getAllValues(configurations);
    }).then(function (chartData) {
        angular.forEach(chartData, function(value, key) {
        chartConfigurations[key].chartData = convertToChartDataset(value);
        chartConfigurations[key].options = {
            animation: false
            };
        });

        vm.configurations = chartConfigurations;
    });
}

function getAllValues(configurations) {
    var promises = [];

    $.each(configurations, function (index, value) {
        promises.push(signalRSvc.getAllValues(value.Id));
    })

    return $q.all(promises);
}

您可以将initSignalR()更改为以下内容吗?

1
2
3
4
5
6
7
8
9
10
function initSignalR() {
    return signalRSvc.initialize().then(function() {                
        return signalRSvc.getPerformanceCounters();
    }).then(function(configurations) {
        log('performance counters configuration downloaded');
        getAllValues(configurations).then(function (resultData) {
            vm.resultData = resultData;
        });
    });
}

我知道它不是很漂亮,但是很显然,即使$ q promises有自己的then方法,jQuery的then方法也显然不能正确地解开$ q promises。