Правильный способ написать неблокирующую функцию в node.js - PullRequest
0 голосов
/ 21 декабря 2018

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

function longRunningFunc(val, mod) {
    return new Promise((resolve, reject) => {
        sum = 0;
        for (var i = 0; i < 100000; i++) {
            for (var j = 0; j < val; j++) {
                sum += i + j % mod
            }
        }
        resolve(sum)
    })
}

console.log("before")
longRunningFunc(1000, 3).then((res) => {
    console.log("Result: " + res)
})
console.log("after")

Вывод выглядит так, как ожидалось:

before     // delay before printing below lines
after
Result: 5000049900000

Но программа ждет, прежде чем печатать вторую и третью строки.Не могли бы вы объяснить, каким должен быть правильный способ сначала печатать «до» и «после», а затем (через некоторое время) результат?

1 Ответ

0 голосов
/ 21 декабря 2018

Упаковка кода в обещание (как вы сделали) не делает его неблокирующим.Функция Promise executor (обратный вызов, который вы передаете new Promise(fn), вызывается синхронно и блокирует, поэтому вы видите задержку в получении вывода.

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

Вы можете использовать такие вещи, как setTimeout(), чтобы изменить «когда» ваш код выполняется, но всякий раз, когда он выполняется, он все равно будет блокировать (если онначинает выполнять больше ничего не может, пока не выполнится.) Все асинхронные операции в библиотеке node.js используют некоторую форму базового собственного кода, которая позволяет им быть асинхронными (или они просто используют другие асинхронные API-интерфейсы node.js, которые сами используют реализации собственного кода).

Но программаждет, прежде чем печатать вторую и третью строки.Можете ли вы объяснить, каким должен быть правильный способ сначала «до» и «после» напечатать, а затем (через некоторое время) результат?

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

Итак, вы могли бы сделать это:

function longRunningFunc(val, mod) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            sum = 0;
            for (var i = 0; i < 100000; i++) {
                for (var j = 0; j < val; j++) {
                    sum += i + j % mod
                }
            }
            resolve(sum)
        }, 10);
    })
}

Это перенесет длительный цикл for на более поздний запуск и может "казаться" неблокирующим, ноэто фактически все еще блокирует - это только бежит позже.Чтобы сделать его действительно неблокирующим, вам нужно использовать один из методов, упомянутых ранее, чтобы вытащить его из основного потока Javascript.

Способы создания фактического неблокирующего кода в файле node.js:

  1. Запустите его в отдельном дочернем процессе и получите асинхронное уведомление, когда это будет сделано.
  2. Используйте новые экспериментальные Рабочие потоки в файле node.js v11
  3. Напишите собственное дополнение собственного кода к node.js и используйте потоки libuv или потоки уровня ОС в своей реализации (или другие инструменты асинхронного уровня ОС).
  4. Создание поверх существующих асинхронных API-интерфейсов иу вас нет собственного кода, который занимает много времени в главном потоке.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...