Асинхронный код, как он работает? Обещания и обратные вызовы

1

Я попытался найти ответ в Интернете и сделал это частично. Но я все еще не могу полностью понять, как JS может запускать ansyncronous код?

Мое видение вещей:

JS дает нам возможность асинхронного программирования. Это означает, что мы можем начать первую задачу, а затем, когда все идет, мы можем начать вторую задачу и т.д. Прежде чем js сможет запустить вторую задачу, она должна быть освобождена от предыдущей задачи. Его можно достичь двумя способами:

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

Таким образом, мы не можем достичь асинхронности, просто написав следующий код:

function doSth( callback ) {
    let arr = [];

    for ( let i=1e6; i > 0; i-- )
        arr.push( i );

    callback();
}

doSth( console.log.bind( null, 'I am callback' );
console.log( 'just a line' );

из-за doSth() содержит только работу js, он будет завершен первым, а затем просто появится "просто строка"? Так что это не асинхронно, не так ли? Но если у нас будет задача файловой системы, установленная в цикле, у нас будет асинхронная функция?

И еще один вопрос: действительно ли обезьяны асинхронны? Как они могут быть асинхронными (я имею в виду, могут ли другие задачи обрабатываться во время обработки обещаний), либо обещает просто имитировать асинхронный код? * Я знаю, есть дополнительная очередь для обещаний.

Маби, я просто не понимаю какую-то базу? Буду рад, если вы сможете объяснить мне, чтобы мои вопросы были более явными для меня.

Показать ещё 5 комментариев
Теги:
ecmascript-6
asynchronous
promise
asynccallback

2 ответа

0
Лучший ответ

Думаю, у вас все в порядке.

Функция doSth является синхронной и будет блокировать основной поток до его завершения. Вы предоставляете только API обратного вызова, но это не значит, что он волшебным образом станет асинхронным.

По правде fs.readFile, весь код JS, который вы пишете, является синхронным, если вы не используете основные функции JS, которые определены как асинхронные (например, fs.readFile, setTimeout, $.ajax({...}).done). Без них вы не можете создавать асинхронное поведение, вам придется писать собственное ядро JS с нуля, с циклом событий (на самом деле, я призываю вас к google и изучать, что такое javascript event loop, я считаю, что это прояснит многие вещи для вас и дадут вам гораздо лучшее представление о том, что происходит в ядре). Все сторонние библиотеки там получают асинхронное поведение просто потому, что они используют эти основные функции и обертывают их собственным кодом, предоставляя более элегантные API-интерфейсы более высокого уровня.

То же самое касается обещаний. Да, они асинхронны, НО ТОЛЬКО, если вы заполняете их асинхронным кодом. В самом деле, у них есть некоторые дополнительные накладные расходы и не запускают код немедленно, но если одно обещание содержит только синхронный код, то его возможное выполнение блокирует основной поток до его завершения.

0

Посмотрите этот плейлист для легкого обзора асинхронного Javascript.

Но если вы действительно хотите понять все подробности, прочитайте эту книгу.

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

Асинхронность - это "когда часть вашей программы выполняется сейчас, а другая часть вашей программы запускается позже - есть промежуток между сейчас и позже, когда ваша программа не активно выполняется".

Рассмотрите свой код:

function doSth(callback) {
  let arr = [];
  for (let i=1e6; i > 0; i--){
    arr.push(i);
  }
  callback();
}

doSth(console.log.bind(null, 'I am callback'));
console.log('just a line');

Это приведет к выводу

Я обратный вызов

затем

просто линия

Однако, если вы изменили код на это:

function doSth(callback) {
  let arr = [];
  for (let i=1e6; i > 0; i--){
    arr.push(i);
  }
  setTimeout(callback, 0);
}

doSth(console.log.bind(null, 'I am callback'));
console.log('just a line');

Ты получишь

просто линия

затем

Я обратный вызов

По сути, это связано с тем, какая функция вызывает ваш обратный вызов. "doSth" не является асинхронной функцией, независимо от того, сколько времени займет цикл for. Во втором примере, однако, setTimeout - это функция, вызывающая ваш обратный вызов, а setTimeout - это асинхронная функция, которая запускается после остальной части вашего синхронного кода только потому, что она работает так. Другой распространенной асинхронной функцией будет любой запрос AJAX, и обратный вызов, предоставленный ему, также будет вызываться после любого другого синхронного кода.

  • 0
    Итак, асинхронность просто: запустить задачу -> приостановить задачу -> продолжить задачу?
  • 2
    Это очень обманчиво и расплывчато.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню