如何使用间隔将 angular 范围绑定到 web worker 的结果?

How to bind angular scope to the result of a web worker using an interval?

我需要根据网络工作者的 "callback" 从我的范围更新一个变量。这些 web workers 基本上是 return 值在特定时间间隔的时间间隔。

这是我的worker.js

var timer = false;
var onmessage = function (e) {
    var value = e.data[0];
    var stock = e.data[1];
    var interval = e.data[2];

    if (timer) {
        clearInterval(timer);
    }

    timer = setInterval(function () {
        stock += value;
        postMessage(stock);
    }, interval)
}

我知道如何使用 promise 从 web worker 获取结果,但正如我所料,它只适用于第一次回调。

app.factory('workerServices', ['$q', function ($q) {
    var worker = new Worker('worker.js'),
        defer = $q.defer();

    worker.onmessage = function (e) {
        console.log('Result worker:' + e.data); //displayed each "interval"
        defer.resolve(e.data);
    }

    return {
        increment: function (value, stock, interval) {
            defer = $q.defer();
            worker.postMessage([value, stock, interval]);
            return defer.promise;
        }
    };
}]);

app.controller('mainCtrl', ['$scope', 'workerServices', function ($scope, workerServices) {
    var value = 1,
        stock = 0,
        interval = 300;

    workServices.increment(val, stock, interval).then(function (newStock) {
        $scope.stock = newStock; //updated once

    });
}]);

所以我尝试将结果直接绑定到范围以查看它是否有效(我不喜欢这样做,因为我想为我的网络工作者使用工厂)。

它没有用。我不知道为什么,但即使 console.log 正常工作,我的范围也保持不变。

app.controller('mainCtrl', function ($scope) {
    var value = 1,
        stock = 0,
        interval = 300;

    var worker = new Worker('worker.js');
    worker.postMessage([value, stock, interval]);
    worker.onmessage = function (e) {
        console.log(e.data) //properly displayed
        $scope.result = e.data; // never updated
    };
});

我在这里错过了什么?我怎样才能 "continuously" 将变量从我的范围更新为网络工作者的结果?

Webworker 事件 onmessage 发生在 angular 上下文之外,因此 angular 摘要系统不知道要更新绑定。在这种情况下,我们需要明确地说 angular 以通过调用 $scope.$apply() 手动启动摘要循环。

我宁愿使用 $timeout,这将是应用摘要循环的最安全方式。因为有时直接 运行 $apply 方法会因与当前 运行 循环冲突而导致 digest cycle is in already progress 错误。

worker.onmessage = function (e) {
    console.log(e.data) //properly displayed
    $timeout(function(){
       $scope.result = e.data; // never updated
    });
};

在第二种情况下,您可以在 $scope.result = data 之后尝试 $scope().$apply() 吗?

在您的第一种情况下,AFAIK 您无法两次解决相同的承诺,这就是您没有得到预期结果的原因。我建议您采用订阅者-监听器模式来实现此 $broadcast/$emit 方法。这tutorial会给你一个好的开始。