Использование обещания для работы с веб-работником в закрытии JavaScript - PullRequest
0 голосов
/ 21 сентября 2018

Я выполнял операцию обработки изображений в JavaScript, которая работала, как и ожидалось, ожидая одного, иногда это зависало от пользовательского интерфейса, что заставляло меня использовать веб-работника для выполнения функций обработки изображений.У меня есть сценарий, где мне нужно обработать несколько.Ниже приведен краткий обзор рабочего процесса, который я использую для достижения вышеуказанного умения.

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

Здесь я загружаю несколько изображений и передаю их в манипулируем функцией.Проблема, с которой я сталкиваюсь здесь в этом сценарии, состоит в том, что иногда для немногих изображений Обещание никогда не решается.После отладки своего кода я понял, что это потому, что я создаю Обещание для изображения, в то время как предыдущее Обещание не было решено.Мне нужны предложения о том, как я могу исправить эту проблему, также у меня есть другой запрос, если я должен использовать одно и то же закрытие (фильтруйте здесь в вышеупомянутом сценарии) несколько раз или создавать новое закрытие каждый раз, когда требуется, как показано ниже:

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

} 

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

Я надеюсь, что моя проблема ясна, если нет, пожалуйста, прокомментируйте.

1 Ответ

0 голосов
/ 21 сентября 2018

Лучше всего было бы загрузить вашу обработку изображений Worker только один раз.во время запуска вашего приложения или когда это необходимо.

После этого вы можете создать Обещание только для функции, которую вы хотите вызвать от работника.В вашем случае filter может возвращать новый объект Promise каждый раз, когда вы публикуете на Worker.Этот объект обещания должен быть разрешен только тогда, когда от рабочего получен ответ на конкретный вызов функции.

Что происходит с вашим кодом, так это то, что ваши обещания разрешаются, даже если обработчик onmessage обрабатывает сообщение, отличное от Worker.то есть.если вы отправляете 2 раза работнику.если второе сообщение возвращает сообщение, оно автоматически разрешает оба ваших объекта обещания.

Я создал рабочую инкапсуляцию здесь Orc.js .Хотя он может не работать из коробки из-за того, что я не очистил его от некоторых зависимостей, которые я в него встроил.Не стесняйтесь использовать методы, которые я применил.

Дополнительно: вам необходимо сопоставить ваши post и onmessage с promises.это потребует от вас также изменения вашего кода работника.

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