Застрял в понимании асинхронного поведения узла JS - PullRequest
0 голосов
/ 08 ноября 2018

Я изучаю обратные вызовы узлов js и асинхронное поведение с этого сайта. Из приведенных примеров я написал следующий код, чтобы лучше понять его.

function callbackTester (callbackFn){
    console.log('From callback tester.');
    callbackFn();
}

function pollingWait(){
    while (true) {}
}

callbackTester(() => {
    console.log('From anonymous function.');
    setTimeout(()=>{
        console.log("I'm waiting!");
    }, 500);
    // pollingWait();
});
console.log('I am the last one');

Теперь, когда я закомментирую функцию pollingWait(), она работает как положено. Это дает следующий вывод:

From callback tester.
From anonymous function.
I am the last one
I'm waiting!

Теперь, когда я закомментирую функцию setTimeout и добавлю pollingWait(), программа заходит в бесконечный цикл. Я думаю, что это также ожидаемое поведение, так как узел js является однопоточным и не может избежать бесконечных циклов. Так как же это асинхронное поведение работает под капотом?

Как он решает, когда продолжать выполнение, а когда нет? Можно ли сделать мою собственную функцию, которая действует как асинхронный, как setTimeout?

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Попробуйте эту вещь:

let done = false;

setTimeout(() => {
  done = true
}, 5);

const eventLoopQueue = () => {
  return new Promise(resolve => 
    setImmediate(() => {
      console.log('event loop');
      resolve();
    })
  );
}

const run = async () => {
  while (!done) {
    console.log('loop');
    await eventLoopQueue();
  }
}

run().then(() => console.log('Done'));
0 голосов
/ 08 ноября 2018

Я думаю, это также ожидаемое поведение, поскольку узел js является однопоточным и не может избежать бесконечных циклов.

Node.js больше не является однопоточным , но есть только один основной поток, если вы не создаете рабочие потоки.

Так как же это асинхронное поведение работает под капотом?

Основной поток Node.js работает в цикле: ваш код верхнего уровня запускается и возвращается, затем запускается и возвращается любое действие в очереди (например, обратный вызов таймера), а затем запускается и возвращается следующее действие в очереди и т. Д. Вот как работает setTimeout: когда пора срабатывать таймеру, цикл обработки событий видит это и ставит в очередь вызов обратного вызова таймера. Также обратите внимание, что хотя Node.js по умолчанию имеет только один основной поток JavaScript, это не означает, что сам Node является однопоточным. В частности, он может выполнять обработку ввода-вывода в другом внутреннем потоке.

Можно ли создать мою собственную функцию, которая будет работать асинхронно, как setTimeout?

Только используя что-то, что уже обеспечивает асинхронное поведение, и упаковывая его. Это будет включать:

  • setTimeout
  • setImmediate
  • process.nextTick
  • Обратный вызов then или catch обещания

На первый взгляд вы можете подумать, что async функции делают это, но на самом деле это не так: код в async функции запускает синхронно вплоть до первого ожидания обещания. разрешение (или до тех пор, пока оно не вернется). Таким образом, асинхронность в действительности такая же, как и в последнем пуле выше: обратный вызов then или catch.

То, что вы не можете сделать (без рабочего потока), занято-ждать, как это делает ваш pollingWait, потому что больше ничего не может произойти с потоком, в котором выполняется занятое ожидание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...