diff --git a/src/util/actor.js b/src/util/actor.js index 940a0030f0b..ac441726c41 100644 --- a/src/util/actor.js +++ b/src/util/actor.js @@ -53,7 +53,7 @@ class Actor { * @param targetMapId A particular mapId to which to send this message. * @private */ - send(type: string, data: mixed, callback: ?Function, targetMapId: ?string): ?Cancelable { + send(type: string, data: mixed, callback: ?Function, targetMapId: ?string, mustQueue: boolean = false): ?Cancelable { // We're using a string ID instead of numbers because they are being used as object keys // anyway, and thus stringified implicitly. We use random IDs because an actor may receive // message from multiple other actors which could run in different execution context. A @@ -68,6 +68,7 @@ class Actor { type, hasCallback: !!callback, targetMapId, + mustQueue, sourceMapId: this.mapId, data: serialize(data, buffers) }, buffers); @@ -110,20 +111,20 @@ class Actor { cancel(); } } else { - // In workers, store the tasks that we need to process before actually processing them. This - // is necessary because we want to keep receiving messages, and in particular, - // messages. Some tasks may take a while in the worker thread, so before - // executing the next task in our queue, postMessage preempts this and - // messages can be processed. We're using a MessageChannel object to get throttle the - // process() flow to one at a time. - this.tasks[id] = data; - this.taskQueue.push(id); - if (isWorker()) { + if (isWorker() || data.mustQueue) { + // In workers, store the tasks that we need to process before actually processing them. This + // is necessary because we want to keep receiving messages, and in particular, + // messages. Some tasks may take a while in the worker thread, so before + // executing the next task in our queue, postMessage preempts this and + // messages can be processed. We're using a MessageChannel object to get throttle the + // process() flow to one at a time. + this.tasks[id] = data; + this.taskQueue.push(id); this.invoker.trigger(); } else { // In the main thread, process messages immediately so that other work does not slip in // between getting partial data back from workers. - this.process(); + this.processTask(id, data); } } } @@ -146,6 +147,10 @@ class Actor { return; } + this.processTask(id, task); + } + + processTask(id: number, task: any) { if (task.type === '') { // The done() function in the counterpart has been called, and we are now // firing the callback in the originating actor, if there is one. diff --git a/src/util/ajax.js b/src/util/ajax.js index 3c3e29605aa..38189d4ef77 100644 --- a/src/util/ajax.js +++ b/src/util/ajax.js @@ -230,7 +230,8 @@ export const makeRequest = function(requestParameters: RequestParameters, callba return makeFetchRequest(requestParameters, callback); } if (isWorker() && self.worker && self.worker.actor) { - return self.worker.actor.send('getResource', requestParameters, callback); + const queueOnMainThread = true; + return self.worker.actor.send('getResource', requestParameters, callback, undefined, queueOnMainThread); } } return makeXMLHttpRequest(requestParameters, callback);