AngularJS承诺$ q.all和SignalR

时间:2014-01-14 09:12:28

标签: javascript angularjs signalr promise q

我已经检查过有关承诺的答案数量,但我无法使我的代码正常工作(也许我在其他地方做了一些非常错误的事情)

总的来说,我正在使用AngularJS和SignalR处理小型测试应用程序。我有signalR服务,看起来像这样:

(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代理方法正在返回承诺。我已经编写了这段代码,但我不知道为什么它不能用于步骤getAllValues(根据这个答案AngularJS Promises, $q, defer它应该有效)

   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应该包含从这些promises返回的对象数组时执行。而不是这个,我得到一些甚至不是阵列的垃圾。

当我做这样的事情时,令人惊讶(对我而言)

    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!!
        });
    }
在嵌套的

然后结果数据很好(但当然解决承诺的顺序搞砸了)。

由于我没有想法,所以提前感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

我的朋友Yan Yankowski为AngularJS写了一篇很棒的 SignalR 包装器。你可以从GitHub download, 此包装器还使用 $ q 承诺来获取结果。

示例:

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

答案 1 :(得分:2)

看起来这个问题与SingalR(我的团队同事发现这个)的承诺有关。 SignalR正在返回jQuery承诺,这些承诺在所有情况下都与AngularJS承诺不兼容。解决方案是使用 $ q.when 来包装来自signalR代理的方法。现在一切正常。

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

.....

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

以前无效的承诺链接现在正常工作

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

答案 2 :(得分:0)

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

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

我知道它并不漂亮,但显然jQuery的方法显然没有正确解开$ q promises,即使$ q promises有自己的方法。