Упаковка кода в обещание (как вы сделали) не делает его неблокирующим.Функция 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:
- Запустите его в отдельном дочернем процессе и получите асинхронное уведомление, когда это будет сделано.
- Используйте новые экспериментальные Рабочие потоки в файле node.js v11
- Напишите собственное дополнение собственного кода к node.js и используйте потоки libuv или потоки уровня ОС в своей реализации (или другие инструменты асинхронного уровня ОС).
- Создание поверх существующих асинхронных API-интерфейсов иу вас нет собственного кода, который занимает много времени в главном потоке.