在JavaScript闭包内使用promise与Web Worker一起使用

时间:2018-09-21 07:01:43

标签: javascript image-processing es6-promise web-worker

我正在用JavaScript执行图像处理操作,该操作按预期工作,有时会冻结UI,这使我不得不使用Web worker来执行图像处理功能。 我有一个需要处理多个的场景。以下是我用于实现上述壮举的工作流的摘要。

//closure
var filter = (function(){
    function process(args){
         var promise = new Promise(function (resolve, reject) {
            if (typeof (Worker) !== "undefined") {
                if (typeof (imgWorker) == "undefined") {
                    imgWorker = new Worker("/processWorker.js");
                }
                imgWorker.postMessage(args);
                imgWorker.onmessage = function (event) {
                    resolve(event.data);
                };
            } else {
                reject("Sorry, your browser does not support Web Workers...");
            }
        });
        return promise;
    }
return {
        process: function(args){
            return process(args);
       }
 }
})(); 

function manipulate(args, callback){
    filter.process(args).then(function(res){
        callback(res);
    });
}

在这里,我正在加载多个图像,并将它们传递到操纵函数中。 在这种情况下,我在这里面临的问题是,有时候对于某些图像,Promise永远不会解决。 在调试我的代码后,我发现这是因为我正在为图像创建Promise,而先前的Promise尚未解决。 我需要有关如何解决此问题的建议,也有另一个查询,我应该多次使用相同的闭包(在上述情况下为此处的过滤器),或者在每次需要时创建新的闭包,如下所示:

var filter = function(){
      ....
    return function(){}
    ....

} 

function manipulate(args, callback){
    var abc = filter();
    abc.process(args).then(function(res){
        callback(res);
    });
}

我希望我的问题很清楚,否则请发表评论。

1 个答案:

答案 0 :(得分:1)

更好的方法是仅一次加载图像处理Worker。在您的应用程序启动期间或需要时。

此后,您只能为希望从工作人员调用的功能创建一个Promise。对于您而言,filter可以在您每次发布到Promise时返回一个新的Worker对象。仅当收到来自工作人员针对特定函数调用的答复时,才应解析此Promise对象。

您的代码正在发生的事情是,即使onmessage处理程序正在处理来自Worker的不同消息,您的诺言也正在解决。即。如果您向员工发布2次。如果第二条帖子返回一条消息,它将自动解析您的两个promise对象。

我在Orc.js处创建了工人封装。尽管由于我尚未清除它内置的某些依赖项,它可能无法立即使用。随意使用我应用的方法。

其他: 您将需要将postonmessage映射到promises。这也需要您修改Worker代码。

//
let generateID = function(args){
  //generate an ID from your args. or find a unique way to distinguish your promises. 
  return id;
}
let promises =  {}
// you can add this object to your filter object if you like. but i placed it here temporarily

//closure
var filter = (function(){
    function process(args){
          let id = generateID(args)
          promises[id] = {}
          promises[id].promise = new Promise(function (resolve, reject) {
            if (typeof (Worker) !== "undefined") {
                if (typeof (imgWorker) == "undefined") {
                    imgWorker = new Worker("/processWorker.js");
                    imgWorker.onmessage = function (event) {
                        let id = generateID(event.data.args) //let your worker return the args so you can check the id of the promise you created.
                        // resolve only the promise that you need to resolve
                        promises[id].resolve(event.data);
                    }    
                    // you dont need to keep assigning a function to the onmessage. 
                }
               
                imgWorker.postMessage(args);
                // you can save all relevant things in your object. 
                promises[id].resolve = resolve
                promises[id].reject = reject
                promises[id].args = args
            } else {
                reject("Sorry, your browser does not support Web Workers...");
            }
        });
        //return the relevant promise
        return promises[id].promise;
    }
return {
        process: function(args){
            return process(args);
       }
}
})(); 

function manipulate(args, callback){
    filter.process(args).then(function(res){
        callback(res);
    });
}

相关问题