Вызов асинхронной функции внутри действия vuex

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

Я сделал следующее (commons.js, отдельный файл javascript):

exports default {
  myHugeFunction: function(params) {
   //lots...lots...lots..of synchronous things
  }
}

Где я это называю?

Модуль магазина Vuejs

import commons from '/path/to/commons'
export default {
  actions: {
    updateInterface: function() {
     //overlay on
     //some syncronous stuff...
      Q.fcall(function () {
        commons.myHugeFunction(params);
      }
     //some others syncronous stuff...
     //overlay off
    }
  }
}

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

Я предполагаю, что это выполнение как что-то, что может быть обработано отдельным потоком, поэтому пользователь в это время может делать другие вещи.

Это потому, что «возможно» приложение полностью находится во внешнем интерфейсе (браузере)?


person Andrea Grimandi    schedule 15.05.2017    source источник
comment
независимо от того, где вы это поместите, если у вас есть огромная синхронная функция, которая блокирует io, она заблокирует io. исправить саму функцию.   -  person Kevin B    schedule 15.05.2017
comment
Большое спасибо за полезный ответ! Теперь проблема ясна. Это общий код с другой командой, которая очень гордится своей работой :D и не может трогать по какой-либо причине (этот код), поэтому мы должны решить проблему, возможно ли это тоже? ДА или НЕТ также может быть хорошим ответом, просто чтобы знать, как мы можем двигаться дальше :)   -  person Andrea Grimandi    schedule 15.05.2017


Ответы (1)


Для этого можно использовать веб-воркер при условии, что myHugeFunction не использует какие-либо глобальные переменные, доступные только в контексте window. Так, например, он не может взаимодействовать с DOM. Вам необходимо передать все внешние зависимости в качестве параметров или включить зависимости в контекст веб-воркера.

Вот как это будет выглядеть:

Переместите myHugeFunction из commons.js в новый отдельный worker.js файл, который не следует import использовать. Ваш файл worker.js должен выглядеть так:

function myHugeFunction(...params) {
   //lots...lots...lots..of synchronous things
   console.log('parameters', params);
   return 'myHugeFunction return value';
}

onmessage = function(e) {
    postMessage(myHugeFunction(...e.data));
}

В вашем commons.js вы можете определить эту вспомогательную функцию promiseWork:

exports default {
    promiseWork: function(script, params) {
        return new Promise(function (resolve, reject) {
            var worker = new Worker(script);
            worker.onmessage = function(e) {
                resolve(e.data);
            }
            worker.onerror = function(e) {
                reject('[' + e.filename + ':' + e.lineno + '] ' + e.message);
            }
            worker.postMessage(params);
        });
    }
}

В вашем модуле хранилища Vuejs вы должны вызвать promiseWork с именем скрипта и параметрами (массивом) в качестве аргументов:

export default {
    actions: {
        updateInterface: function() {
            //overlay on
            //some synchronous stuff...
            promiseWork('worker.js', params).then(function () {
                console.log('huge work completed asynchronously');
                //some other stuff...
                //overlay off
            });
        }
    }
}
person trincot    schedule 16.05.2017