Прежде всего, я поставил его в начале статьи, акцентируя внимание на двух моментах:
- JavaScript — это однопоточный язык.
- Цикл событий — это механизм выполнения JavaScript.
Хорошо, тогда приступим к основному содержанию этой статьи.Так как js однопоточный, значит он выполняется сверху вниз при выполнении кода.Возьмем кусок кода:
setTimeout(function(){
console.log('定时器开始')
});
new Promise(function(resolve){
console.log('Promise开始');
resolve();
}).then(function(){
console.log('执行then函数')
});
console.log('代码执行结束');
Увидев приведенный выше код, вы можете дать ответ: «Таймер запускается», «Промис начинается», «Выполняется, затем функция», «Выполнение кода заканчивается». Затем давайте проверим, что вывод:
- Обещание начинается
- выполнение кода заканчивается
- выполнить функцию then
- таймер запускается
Одиночный поток JavaScript
Увидев такой ответ, давайте изучим механизм его выполнения. Что касается предварительного парсинга, я опубликую отдельную статью позже. Здесь мы в основном рассмотрим механизм выполнения, лежащий в основе. Мы говорим, что JavaScript — это однопоточный язык. откуда взялась его "многопоточность"? Все это смоделировано. Давайте через некоторое время взглянем на этого "многопоточного бумажного тигра".
Синхронный и асинхронный JavaScript (первый взгляд на цикл событий)
Поскольку это один поток, мы можем думать, например, о том, чтобы пойти в банк, чтобы справиться с делами, и когда мы доберемся туда, нам придется встать в очередь, чтобы обработать одну за другой. Те же задачи JavaScript также выполняются одна за другой. , Если первый занимает много времени, то последний должен подождать. , дождитесь завершения предыдущего выполнения, прежде чем продолжить. Теперь, когда мы открываем определенный веб-сайт, мы обычно видим какие-то картинки с фоновыми картинками, потому что некоторые картинки, видео и большие объемы данных на странице занимают очень много времени.Знайте, она пустая~ Так что теперь есть синхронные и асинхронные! ~
- Синхронные и асинхронные задачи входят в разные среды выполнения, синхронно входят в основной поток и асинхронно записываются в список событий таблицы событий.
- Когда событие завершено, задача из списка событий помещается в очередь событий очереди событий, ожидая выполнения.
- После того, как основной поток выполнит все задачи, он проверит очередь событий и, если таковые имеются, вытащит ее и выполнит.
- Вышеуказанные шаги будут повторяться до тех пор, пока не останется исполняемой задачи, образующей цикл событий;
axios.post('/user', { name: 'fly', age: '30' })
.then(function (response) {
console.log(response);
})
console.log('代码执行结束');
- axios входит в список событий. Начните выполнение основного потока и получите console.log("Конец выполнения кода");
- Затем выполняется axios и возвращается функция для входа в очередь событий Event Queue;
- У основного потока нет задачи, и он обращается к очереди событий, чтобы получить ее, и получает функцию обратного вызова для выполнения;
setTimeout
Я считаю, что setTimeout знаком не всем, и его можно использовать в работе, асинхронных функциях и отложенном выполнении~
setTimeout(() => {
console.log('执行setTimeout');
},3000)
console.log('执行console');
Согласно нашей предыдущей идее, сначала выполнить console.log('выполнить консоль'); затем выполнить console.log('выполнить setTimeout'); ответ правильный, затем снова изменить его:
setTimeout(() => {
abc();
},3000)
exercise(100000000);//假设有个运动函数,需要时间很长...而且不固定...大于3秒,可能10秒
Затем мы запускаем результаты и обнаруживаем, что console.log('execute setTimeout') не выполняется через 3 секунды;
- Асинхронная функция setTimeout передается асинхронной задаче и записывает список событий.
- Основная программа выполняет функцию упражнения, 1 секунда, 2 секунды, 3 секунды... Ожидание.
- Через три секунды abc() помещается в очередь событий Event Queue и ожидает выполнения, но функция упражнения еще не выполнена, так что просто подождите~
- Наконец, выполнение завершено, нужно перейти в очередь событий, чтобы найти задачу для выполнения, а abc() входит в основной поток и выполняет ее.
После завершения вышеуказанного процесса мы знаем, что функция setTimeout добавляет задачу для выполнения (abc() в этом примере) в очередь событий через указанное время, и поскольку это однопоточная задача, ее необходимо выполняется одна за другой. Предыдущая задача занимает слишком много времени, поэтому вам остается только ждать, в результате чего реальное время задержки намного превышает 3 секунды. Иногда мы видим форму setTimeout(function(),0); Выполняется ли 0 секунд сразу? не совсем
Тогда его сознание состоит в том, что для входа в Очередь событий не требуется много секунд, и когда основная задача потока будет завершена, он вернется к выполнению. Или предыдущий пример:
setTimeout(() => {
abc();
},0)
console.log('执行console');
// 1.执行console 2.abc()
Позвольте мне рассказать об этом здесь.На самом деле я видел, что автор сказал, что setTimeout имеет ограничение минимального интервала времени.Стандарт HTML5 составляет 4 мс, и если он меньше 4 мс, он обрабатывается по 4 мс, но минимальный интервал реализуется каждым браузером по-разному. Минимальный интервал для setInterval составляет 10 миллисекунд, то есть интервал менее 10 миллисекунд будет скорректирован до 10 миллисекунд. Сделайте заметку здесь.
setInterval
У двух братьев-таймеров один и тот же принцип, за исключением того, что setInterval будет помещать зарегистрированную функцию в очередь событий каждый указанный момент времени. Если время предыдущей задачи слишком велико, она также будет ждать, но обратите внимание, если время выполнения других функций слишком велико, таймер завершит выполнение и возьмет эти задачи из списка времени в очередь событий. , за пределами отложенного времени выполнения, тогда основная программа будет выполняться одна за другой, и время задержки не будет видно.
Promise
Вот краткое введение в роль Promise, и я не буду много говорить о деталях (еще много чего можно подытожить...), Объекты Promise используются для асинхронных операций. В реальной разработке мы столкнемся с такой ситуацией:
$.ajax({
url:www.javascript.com,
data:data,
success:() => {
console.log('第一个数据返回成功!');
$.ajax({
url:www.javascript.com,
data:data,
success:() => {
console.log('第二个数据返回成功!');
...如果还有再继续
}
})
}
})
Увидев этот код, вы должны быть знакомы с ним. Я думаю, вы уже сталкивались с ним раньше. "Выглядит довольно хорошо, это довольно хорошо~~~"! Я думаю, вы гей, старик очень плохой~, теперь Обещание отправлено Используется:
function abc(url,param){
return new Promise(function (resolve, reject) {
request(url, param, function(){
resolve('数据请求成功了');
}, reject);
});
}
abc.then(function(data){
console.log(date);//'第一个数据请求成功了';
return new Promise(function (resolve, reject) {
request(url, param, function(){
resolve('数据请求成功了');
}, reject)
});
}).then(function(){
console.log(date);//'第二个数据请求成功了';
});
Я не буду здесь больше говорить об использовании Promise.Продолжим нашу тему.Помимо обобщенных синхронных задач и асинхронных задач у нас есть более уточненное определение задач:
- Задача макроса содержит весь блок кода скрипта, setTimeout, setInterval
- Обещание микрозадачи, process.nextTick (здесь не описано)
Различные типы задач будут попадать в соответствующую очередь событий Очередь событий, например, setTimeout и setInterval будут попадать в одну и ту же очередь событий. Обещание и process.nextTick войдут в то же самое.
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
resolve();
}).then(function() {
console.log('then');
})
console.log('console');
Результат выполнения: обещание, консоль, затем setTimeout
- Этот код входит в основной поток как задача макроса.
- Сначала см. setTimeout, затем зарегистрируйте его и поместите в очередь событий очереди событий задачи макроса.
- Далее идет промис, сразу же выполняется новый промис, а функция then распределяется по очереди событий микрозадачи.
- Когда встречается console.log(), он выполняется немедленно.
- Выполнение первой задачи макроса на данный момент завершено. Затем мы должны посмотреть, есть ли микрозадачи, да, есть, взять их и выполнить.
- Первый виток цикла событий закончен, начинаем второй виток цикла, естественно, начиная с макрозадачи Event Queue. Мы нашли callback-функцию, соответствующую setTimeout, в макрозадаче Event Queue и тут же ее выполнили.
- Исполнение заканчивается.
Связь между циклом событий, макрозадачей и микрозадачей показана на рисунке (здесь я вижу картинку, используемую многими авторами, я тоже туда зайду, спасибо автору картинки):
Затем я получаю кусок кода ниже, который также можно увидеть в Интернете:
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
附上输出结果:1,7,6,8,2,4,3,5,9,11,10,12
Я хотел бы поблагодарить авторов за их статьи (csdn, Zixiao), которые я видел в Интернете. Я думаю, что написание очень хорошее. Я также имитирую его здесь, чтобы записать его и добавить свое собственное мнение. Я надеюсь помочь большему количеству людей. ~~~