连续WebWorker通信和查询

时间:2015-06-22 14:21:26

标签: javascript angularjs web-worker

我正在尝试创建一个WebWorker,我的意思是我已经创建了它,它在一个Angular应用程序中,我想查询该工作者的各种事情,主要是权限(不需要像“这不是那种资源密集的答案”对于用户工作者等,我计划将来在这些网络工作者上卸载更多的工作“)。

问题是我似乎丢失了一些消息 - 因为我在它上面扔了3-4个请求而我只收到2个回复,或者像这样的东西,我放弃了这个东西2个月前,我想在这里再提一个问题。

代码如下所示:

.factory('permissionsWorker', ['$q', '$timeout', function ($q, $timeout) {

        'use strict';

        // Returns a function, that, as long as it continues to be invoked, will not
        // be triggered. The function will be called after it stops being called for
        // N milliseconds. If `immediate` is passed, trigger the function on the
        // leading edge, instead of the trailing.
        function debounce(func, wait, immediate) {
            var timeout;
            return function() {
                var context = this, args = arguments;
                var later = function() {
                    timeout = null;
                    if (!immediate) {func.apply(context, args);}
                };
                var callNow = immediate && !timeout;
                clearTimeout(timeout);
                timeout = setTimeout(later, wait);
                if (callNow) {func.apply(context, args);}
            };
        }

        var makeWorker;

        var myWorker = new Worker('/src/workers/permissionsWEeBWorkerSource.js');


        makeWorker = function(functionName, functionParams) {
            //console.log('makeWorker instance for ', functionName);
            var deferred;
            deferred = $q.defer();

            myWorker.postMessage({
                'functionName': functionName,
                'functionArgs': Array.prototype.slice.call(functionParams)
            });

            myWorker.onmessage = function(oEvent) {

                if (oEvent.data) {
                    console.info('Worker responded TRUE', oEvent.data);
                    deferred.resolve(oEvent.data);
                } else {
                    console.info('Worker responded FALSE', oEvent.data);
                    deferred.reject('Action not allowed');
                }
            };

            return deferred.promise;
        };

        return {

            canI: function canI(permission){
                return makeWorker('canI', [permission]); // jshint ignore:line
            },
            setRole: function setRole(role){
                return makeWorker('setRole', [role]);
            },
            setRoleSettings: function setRoleSettings(roleSettings){
                return makeWorker('setRoleSettings', [roleSettings]);
            },
            setActions: function setActions(allActions){
                return makeWorker('setActions', [allActions]);
            }

            /*f: function f(functionName, functionParams) {

             if (arguments.length < 2) {
             throw new TypeError('Not enough arguments. ' +
             'The first param is a function name as string. ' +
             'The second is an array of data types');
             }

             if (typeof arguments[0] !== 'string') {
             throw new TypeError('First parameter must be a string. ' +
             'This is the name of the function');
             }

             if (!Array.isArray(arguments[1])) {
             throw new TypeError('Second parameter must be an array. ' +
             'This is an array of data to be processed');
             }

             return makeWorker(functionName, functionParams);

             }*/

        };

    }

工人本身看起来像这样:

/*global onmessage:true */

'use strict';

/** Methods:
 * - canI > param string
 * - setRole > param string
 * - setRoleSettings > param object
 * - setActions > param object
 * */

var role, roles, roleSettings, actions;


var functionsObject = {

    canI: function canI(permission) {
        console.group('WebWorker - Ask for permission:');
        console.info(permission);
        console.groupEnd();
        //TODO: Logic here
        postMessage(true); // jshint ignore:line
    },

    setRole: function setRole(activeRole) {

        console.group('WebWorker - Role received');
        console.table(actions);
        console.groupEnd();

        role = activeRole;

        //TODO: Logic here
        postMessage(true); // jshint ignore:line
    },

    setRoleSettings: function setRoleSettings(settings) {
        console.group('WebWorker - Role Settings received');
        console.table(settings);
        console.groupEnd();
        //TODO: Logic here
        postMessage(true); // jshint ignore:line
    },

    setActions: function setActions(actions) {
        console.group('WebWorker - Configuration received');
        console.table(actions);
        console.groupEnd();
        //TODO: Logic here
        postMessage(true); // jshint ignore:line
    }
};



onmessage = function onmessage(oEvent) {
  if (oEvent.data instanceof Object &&
    oEvent.data.hasOwnProperty('functionName') &&
    oEvent.data.hasOwnProperty('functionArgs')) {

    functionsObject[oEvent.data.functionName].apply(self, oEvent.data.functionArgs);

  }

};

我知道工人本身主要用于单个用例 - 单用例,但似乎对我来说只有一半工作。我提供了一些数据,然后我查询它的回复,我想知道我做错了,也许是承诺左右。

我会继续尝试做这项工作,希望我也会从这里得到一些好的反馈。

谢谢!

1 个答案:

答案 0 :(得分:0)

看起来每次调用工作人员时,都会设置一个新的onmessage回调。如果之前的呼叫尚未返回,那么当它发生时,它将尝试解析/拒绝另一个呼叫的承诺,这可能会显示消息丢失,因为每个承诺只能被解析/拒绝一次。

对此进行排序的一种方法是为工作者提供一个永久onmessage回调,并为每个工作者提供一个请求

  • 创建唯一ID
  • 按此ID存储延期对象
  • 将id与工作所需的实际数据一起传递给工作人员

然后当worker完成时,它可以将id传递回主线程,主线程可以检索与该id相关联的延迟对象,并适当地解析/拒绝其承诺。