如何使用interval将angular作用域绑定到web worker的结果

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

本文关键字:web worker 结果 绑定 作用域 何使用 interval angular      更新时间:2023-09-26

我需要根据web工作者的"回调"从我的作用域更新一个变量。这些web worker基本上是一个间隔,在一个特定的间隔返回值。

这是我的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)
}

我知道如何使用承诺从web工作者获得结果,但是,正如我所料,它只适用于第一次回调。

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

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

它没有工作。我不知道为什么,但我的范围保持不变,即使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
    };
});

我在这里错过了什么?我怎样才能"连续"地从我的作用域更新一个变量到一个网络工作者的结果?

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()吗?

在你的第一种情况下,我敢说你不能解决相同的承诺两次,这就是为什么你没有得到你期望的结果的原因。我建议您采用订阅者-侦听器模式来实现这个$broadcast/$emit方法。