2015-07-11 3 views
1

У меня есть ряд слайдеров пользовательского интерфейса (dat.GUI), и я отправляю значения слайдера веб-работнику всякий раз, когда слайдер пользовательского интерфейса изменился.
Расчеты, выполненные работнику, должны составлять около 3-8 секунд, пока работник не отправит обратно необходимую мне информацию.

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

Я начинаю работать с рабочими, поэтому на данный момент я использую только свойство Worker.onmessage и метод Worker.postMessage().Javascript Web Worker - Как игнорировать все сообщения, кроме последнего?

+0

Сообщите нам подробнее о вашей архитектуре. Как теперь рабочий, который является последним сообщением? Если это известно заранее, то почему другие сообщения отправляются работнику в первую очередь? – doldt

+0

Как насчет использования ['debounce'] (http://stackoverflow.com/q/24004791/1233508)? Это задерживает обработку бит, и если во время этой задержки получено новое сообщение, он отбрасывает первый и задерживает новый бит, повторяя его до тех пор, пока сообщения не прекратятся. – DCoder

+0

@doldt Все сообщения отправляются, потому что каждый раз, когда изменяется одно значение ползунка, должны выполняться новые вычисления, но в то же время пользователь может продолжать использовать или останавливать использование ползунков в любое время, поэтому я не знаю, какое последнее сообщение отправить только это. «Как бы работник знал, что является последним сообщением», я думаю, это часть моего собственного вопроса. – des

ответ

2

Это не имеет ничего общего с WebWorker. Это похоже на типичный вариант использования debounce. Проблема здесь в том, что как только ваш рабочий получит сообщение, как он узнает, что он последний? Он не может сказать о будущем. Он не знает, сделает ли пользователь другое взаимодействие с пользовательским интерфейсом в ближайшем будущем. Таким образом, решение подобных проблем - это отговорка. Идея состоит в том, что вы не выполняете свой код сразу, но подождите немного, скажем, 200 мс. В течение этого периода времени, если было другое сообщение, тогда он будет ждать еще 200 мс, ничего не делая. Вы можете реализовать что-то подобное по своему усмотрению, или вы можете импортировать и использовать одну из существующих библиотек, как underscore.js

EDIT: Вот пример использования underscore.js/lodash (оба имеют аналогичный API). Предположим первоначально, ваш код был что-то вроде этого:

onmessage = function(e) { 
    var params = e.data.something; 
    // TODO: Do something with params. 
}; 

С дребезга, вы будете переписывать его как ...

onmessage = _.debounce(function(e){ 
    var params = e.data.something; 
    // TODO: Do something with params. 
}, 200); 

То, что здесь происходит, что _.debounce возвращает функцию-оболочку, которая может быть вызвана как это часто бывает необходимо. Однако это не приведет к немедленной активации функции, завершенной внутри. Он планирует его выполнить в 200 мс (подстройте его для своих нужд). В течение этого периода, если был другой вызов, ранее запланированное выполнение будет отменено, а новое исполнение будет запланировано на 200 мс на этом этапе. Когда время закончится, ваша функция будет выполнена с последней версией аргументов. Теперь вы, вероятно, задаетесь вопросом, что происходит с аргументами предыдущих вызовов? Ответ заключается в том, что они просто отбрасываются функцией обертки. Обратите внимание, что аргументы, переданные в onmessage, сначала передаются в функцию-оболочку, которая сохраняет только последнюю, которая будет передана в завернутую функцию. Вы можете играть с созданным здесь fiddle, чтобы увидеть его в действии. Еще одно примечание, которое я хочу добавить, это то, что вы можете сделать эту логику debounce в своем основном потоке, прежде чем передавать его в WebWorker.

EDIT: Если вам необходимо руководство по импорту сторонней библиотеки в WebWorker. https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Importing_scripts_and_libraries

+0

Я решил использовать debounce. Я знаю, как импортировать библиотеку в WebWorker, но я все еще запутался в том, как реализовать эту функцию. Прямо сейчас, у моего работника у меня есть: onmessage = function (e) { // (1 - получить значения, которые были отправлены из основного потока) sliderValues ​​= e.data.sliderValues; // (2 - выполнить вычисления) getMeshInformation(); // (3 - опубликованные результаты) postMessage ({ 'треугольники: треугольники }); }; теперь я только хочу, чтобы 1 выполнялся, а затем ждать (debounce) для no.2 + 3, если он получает новый № 1, который перезаписывает предыдущий. – des

+0

Если вы используете одну из существующих реализаций, все, что вам действительно нужно сделать, это обернуть ваш оригинальный ответ «onmessage» с помощью debounce, и это все, что есть. Однако, если вы хотите сделать свою собственную реализацию, вы можете посмотреть на [underscore.js] (https://github.com/jashkenas/underscore/blob/master/underscore.js#L821) или [lodash] (https://github.com/lodash/lodash/blob/master/lodash.js#L7655) для некоторых вдохновляющих источников. Конечно, ваша реализация не обязательно должна быть такой фантазией. Я отредактирую свой ответ выше, чтобы включить пример, потому что комментарий в комментарии является уродливым. – initialxy

+0

Спасибо за ваше время, это очень полезно. – des

Смежные вопросы