Тесно связан с синхронизацией JS, асинхронностью и опросом событий.

JavaScript ECMAScript 6

Автор: Сухджиндер Арора Переводчик: Front-end Xiaozhi Источник: среда

Ставь лайк и смотри, поиск в WeChat【Переезд в мир】Обратите внимание на этого человека, который не имеет большого фабричного прошлого, но имеет восходящий и позитивный настрой. эта статьяGitHub GitHub.com/QQ449245884…Он был включен, статьи были классифицированы, и многие мои документы и учебные материалы были систематизированы.

Все говорили, что нет проекта для написания резюме, поэтому я помог вам найти проект, и это было с бонусом.【Учебник по строительству】.

JSявляется однопоточным языком программирования, что означает, что одновременно может обрабатываться только одна вещь, т.JSМеханизм может обрабатывать только один оператор в одном потоке за раз.

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

Представьте, что вы запрашиваете какие-то данные у API: в зависимости от ситуации серверу требуется некоторое время для обработки запроса, блокируя основной поток, в результате чего веб-страница долгое время не отвечает. Вот почему был введен асинхронный JS. Используйте асинхронность (например, функции обратного вызова,promise,async/await), который может длительное время выполнять сетевые запросы, не блокируя основной поток.

Прежде чем мы поймем, как работает асинхронность, давайте посмотрим, как работает синхронизация.

Как работает синхронный JS?

Углубленное изучение асинхронностиJSПеред этим разберемся с синхронизациейJSкод находится вJavaScriptисполнение в двигателе. Например:

    const second = () => {
      console.log('Hello there!');
    }
    
    const first = () => {
      console.log('Hi there!');
      second();
      console.log('The End');
    }
    
    first();

Чтобы понять, как приведенный выше код работает вJSВ двигателе надо понимать что такоеконтекст выполненияа такжестек вызовов(также известный как стек выполнения).

Код функции выполняется в контексте выполнения функции, а глобальный код выполняется в глобальном контексте выполнения. Каждая функция имеет свой собственный контекст выполнения.

стек вызовов

Как следует из названия, стек вызовов имеетLIFOСтек структур (последний вошел, первый вышел), используемый для хранения всех контекстов выполнения, созданных во время выполнения кода.

JSСуществует только один стек вызовов, потому что это однопоточный язык программирования. Стек вызовов имеетLIFOструктура, что означает, что элементы могут быть добавлены или удалены только из вершины стека.

Возвращаясь к приведенному выше коду, попытайтесь понять, как кодJSвыполняется в двигателе.

const second = () => {
  console.log('Hello there!');
}
const first = () => {
  console.log('Hi there!');
  second();
  console.log('The End');
}
first();

Что тут происходит?

Когда этот код выполняется, глобальный контекст выполнения (представленный main() ) создается и помещается на вершину стека вызовов. при встречеfirst(), он помещается на вершину стека.

Следующий,console.log('Hi there!')помещается на вершину стека, а когда это делается, он извлекается из стека. После этого звонимsecond(),следовательноsecond()Функции помещаются на вершину стека.

console.log('Hello there!')помещается на вершину стека и извлекается из стека по завершении.second()Функция завершается, поэтому она выталкивается из стека.

console.log(“the End”)помещается на вершину стека и удаляется по завершении. Позже,first()Функция завершается, поэтому удалите ее из стека.

В этот момент программа завершает свое выполнение, поэтому глобальный контекст выполнения (main()) извлекается из стека.

Как работает асинхронный JS?

Теперь, когда мы сделали стек вызовов и синхронизациюJASС базовым пониманием того, как это работает, вернемся к асинхронности.JSначальство.

Что блокирует?

Предположим, мы выполняем обработку изображений или сетевые запросы синхронно. Например:

const processImage = (image) => {
  /**
  * doing some operations on image
  **/
  console.log('Image processed');
}
const networkRequest = (url) => {
  /**
  * requesting network resource
  **/
  return someData;
}
const greeting = () => {
  console.log('Hello World');
}
processImage(logo.jpg);
networkRequest('www.somerandomurl.com');
greeting();

Требуется время для обработки изображений и сетевых запросов, когдаprocessImage()Когда функция вызывается, это занимает некоторое время в зависимости от размера изображения.

processImage()Когда функция завершится, она будет удалена из стека. тогда позвониnetworkRequest()функцию и поместите ее в стек. Кроме того, для завершения выполнения требуется некоторое время.

Наконец, когдаnetworkRequest()Когда функция завершится, вызовитеgreeting()функция.

Поэтому нам приходится ждать таких функций, какprocessImage()илиnetworkRequest()Заканчивать. Это означает, что эти функции блокируют стек вызовов или основной поток. Таким образом, выполняя приведенный выше код, мы не можем делать ничего другого, что не идеально.

Каково решение?

Самое простое решение — это асинхронные обратные вызовы, которые вы, ребята, используете, чтобы сделать ваш код неблокирующим. Например:

const networkRequest = () => {
  setTimeout(() => {
    console.log('Async Code');
  }, 2000);
};
console.log('Hello World');
networkRequest();

используется здесьsetTimeoutметод имитации сетевого запроса. пожалуйста, помнитеsetTimeoutнетJSчасть двигателя, этоWeb Apiчасть.

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

Опрос событий, веб-API и очередь сообщений неJavaScriptЧасть движка, но браузерJavaScriptСреда выполнения или часть среды выполнения Nodejs JavaScript (для Nodejs). В Nodejs веб-api заменен на c/c++ api.

Теперь вернемся к приведенному выше коду и посмотрим, как он выполняется асинхронно.

const networkRequest = () => {
  setTimeout(() => {
    console.log('Async Code');
  }, 2000);
};

console.log('Hello World');

networkRequest();

console.log('The End');

Когда приведенный выше код загружается в браузере,console.log(' Hello World ')помещается в стек и извлекается из стека по завершении. Далее вы столкнетесьnetworkRequest()вызов, тем самым подтолкнув его к вершине стека.

СледующийsetTimeout()Функция вызывается, поэтому она помещается на вершину стека.setTimeout()Есть два параметра:

    1. обратный вызов и
    1. Время в миллисекундах (мс).

setTimeout()Метод запускает 2-секундный таймер в среде веб-API. В настоящее время,setTimeout()Завершено и извлечено из стека.cosole.log(“the end”)помещается в стек, выполняется после завершения и удаляется из стека.

Тем временем таймер истек, и теперь обратный вызов помещается в очередь сообщений. Но обратный вызов не выполняется сразу, здесь начинается опрос событий.

опрос событий

Задача опроса событий состоит в том, чтобы прослушивать стек вызовов и определять, пуст ли стек вызовов. Если стек вызовов пуст, он проверит очередь сообщений, чтобы увидеть, есть ли какие-либо ожидающие выполнения обратные вызовы.

В этом случае очередь сообщений содержит обратный вызов, а стек вызовов в этот момент пуст. Таким образом, опрос событий помещает обратные вызовы на вершину стека.

Послеconsole.log(“Async Code”)помещается на вершину стека, выполняется и извлекается из стека. В этот момент обратный вызов завершен, поэтому он удаляется из стека, и программа наконец завершается.

Очередь сообщений также содержит обратные вызовы от событий DOM, таких как события щелчка и события клавиатуры. Например:

document.querySelector('.btn').addEventListener('click',(event) => {
  console.log('Button Clicked');
});

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

Аналогично, опрос событий проверяет, пуст ли стек вызовов, и помещает обратные вызовы событий в стек, когда стек вызовов пуст, и выполняет обратный вызов.

Задержка выполнения функции

мы также можем использоватьsetTimeoutчтобы отложить выполнение функции до тех пор, пока стек не будет опустошен. Например

const bar = () => {
  console.log('bar');
}
const baz = () => {
  console.log('baz');
}
const foo = () => {
  console.log('foo');
  setTimeout(bar, 0);
  baz();
}
foo();

распечатать результат:

foo
baz
bar

Когда этот код запускается, первая функцияfoo()ВызыватьfooВнутренне мы называемconsole.log('foo'),ПотомsetTimeout()называется,bar()в качестве функции обратного вызова и когда0секундный таймер.

Теперь, если бы мы не использовалиsetTimeout, bar()Функция выполнится немедленно, но используйтеsetTimeoutа также0секундный таймер, будетbarВыполнение откладывается до тех пор, пока стек не станет пустым.

0секунд спустя,bar()Обратный вызов помещается в очередь сообщений, ожидающих выполнения, но он будет выполнен только тогда, когда стек полностью опустеет, то есть вbazа такжеfooпосле завершения функции.

очередь задач ES6

Мы видели, как выполняются асинхронные обратные вызовы и события DOM, они используют очередь сообщений для хранения ожидания выполнения всех обратных вызовов.

ES6 представил концепцию очереди задач, очередь задачJSсерединаpromiseИспользовал. Разница между очередью сообщений и очередью задач заключается в том, что приоритет очереди задач выше, чем у очереди сообщений, а это означает, чтоpromiseЗадание будет выполнено перед обратным вызовом в очереди сообщений, например:

const bar = () => {
  console.log('bar');
};

const baz = () => {
  console.log('baz');
};

const foo = () => {
  console.log('foo');
  setTimeout(bar, 0);
  new Promise((resolve, reject) => {
    resolve('Promise resolved');
  }).then(res => console.log(res))
    .catch(err => console.log(err));
  baz();
};

foo();

распечатать результат:

foo
baz
Promised resolved
bar

мы можем видетьpromiseсуществуетsetTimeoutвыполнен раньше, потому чтоpromiseОтветы хранятся в очередях задач, которые имеют более высокий приоритет, чем очереди сообщений.

резюме

Итак, мы узнали об асинхронностиJSкак это работает, и такие понятия, как стеки вызовов, циклы событий, очереди сообщений и очереди задач, которые вместе составляютJSСреда выполнения.虽然成为一名出色的JSРазработчикам не нужно изучать все эти концепции, но знать их полезно.

Ошибки, которые могут существовать после развертывания кода, не могут быть известны в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку журнала.Кстати, я рекомендую всем полезный инструмент мониторинга ошибок.Fundebug.

оригинал:blog.bit SRC.IO/понять я…

общаться с

Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.