Я пытаюсь написать простой асинхронный код в JS, но, похоже, он не работает
function order(number) {
console.log("Queuing order: " + number);
for (var i = 0; i < 1000000000; i++); // kill time
console.log("Order: " + number + " completed");
}
function takeOrder(number, cb) {
console.log("Preparing order: " + number + "");
}
console.log("Starting to accept order");
for (var i = 0; i < 3; i++) {
console.log("Taking order: " + i);
takeOrder(i, order(i));
}
console.log("Job completed!");
2 ответа
Я пытаюсь написать простой асинхронный код в JS...
Ничто в вашем коде не является асинхронным. Также в этом коде
takeOrder(i, order(i));
ты звонишь order
и проходя в i
, затем передав его возвращаемое значение (undefined
) в takeOrder
, Пройти order
в takeOrder
вместо этого удалите (i)
:
takeOrder(i, order);
Я пытаюсь заставить его работать, так как пока заказ (номер) занят выполнением, программа продолжает отображать сообщения "Подготовка заказа: .." и "Получение заказа: .."
JavaScript в браузерах запускается в одном основном потоке с доступом к пользовательскому интерфейсу, а затем в ноль или более созданных вами веб-рабочих потоков. Если for
Цикл в вашем коде выполняется в основном потоке пользовательского интерфейса, во время его выполнения больше ничего не может произойти из-за семантики выполнения сценариев JavaScripts.
Если работа представлена for
цикл является синхронным, вам не нужно ничего делать, просто ваша симуляция с использованием for
петля не была точной моделью вашей реальной работы. Например, если он делает запрос ajax.
Если работа представлена for
цикл полностью синхронен, как ваш for
цикл, я бы, наверное, разгрузить for
Цикл для веб-работника:
worker.js
:
self.addEventListener("message", function(e) {
if (e.data && e.data.command == "go") {
for (var i = 0; i < 1000000000; i++); // kill time
self.postMessage({command: "log", message: "Order: " + e.data.order + " completed"});
}
});
Ваш основной файл JS:
function order(number) {
var w = new Worker("worker.js");
w.addEventListener("message", function(e) {
if (e.data && e.data.command == "log") {
console.log(e.data.message);
}
w = null;
});
console.log("Queuing order: " + number);
w.postMessage({command: "go", order: number});
}
function takeOrder(number, cb) {
console.log("Preparing order: " + number + "");
cb(number); // Call the callback
}
console.log("Starting to accept order");
for (var i = 0; i < 3; i++) {
console.log("Taking order: " + i);
takeOrder(i, order); // Pass order as the callback
}
console.log("Job completed!");
Это создает нового работника для каждого заказа, поэтому они могут перекрываться.
Выход:
Начиная принимать заказ Принимая заказ: 0 Подготовка заказа: 0 Порядок очередей: 0 Принимая заказ: 1 Подготовка заказа: 1 Порядок очередей: 1 Принимая заказ: 2 Подготовка заказа: 2 Порядок очередей: 2 Работа завершена! Заказ: 0 выполнено Заказ: 1 выполнено Заказ: 2 выполнено
Обратите внимание, как основной поток сообщает рабочему начать через сообщение, а рабочий сообщает о завершении обратно основному потоку через сообщение.
Улучшения, которые вы могли бы сделать:
order
может вернутьPromise
это выполняется, когда работник заканчивает свою работу.- Вы можете подождать, чтобы опубликовать "Работа завершена", пока все обещания заказа не будут выполнены.
- Рабочий может публиковать промежуточные обновления своего прогресса обратно в главный поток.
- Очевидно, что вы могли бы включить более значимую информацию в сообщения между рабочими потоками и основным потоком.
Идея веб-работника сделала свое дело, и я смог придумать эквивалентный скрипт node.js
const Worker = require('webworker-threads').Worker;
var myWorker = new Worker(function() {
onmessage = function(event) {
console.log("Received order " + event.data.orderNumber + " and it is being processed");
for (var i = 0; i <= 100000000; i++); // processing time.
postMessage("Order " + event.data.orderNumber + " has been successfully processed");
}
});
for (var i = 0; i < 3; i++) {
console.log("Taking order number: " + i);
myWorker.postMessage({
orderNumber: i
});
myWorker.onmessage = function(event) {
console.log(event.data);
}
}
console.log("Completed accepting orders!");
И вывод выглядит следующим образом:
Taking order number: 0
Taking order number: 1
Received order 0 and it is being processed
Taking order number: 2
Completed accepting orders!
Received order 1 and it is being processed
Received order 2 and it is being processed
Order 0 has been successfully processed
Order 1 has been successfully processed
Order 2 has been successfully processed