Битва за порядок выполнения, вызванная использованием nextTick Vue

Node.js JavaScript Vue.js

начало

существуетVueодин изnextTickметодом, случайно однажды я обнаружил, что независимо от порядка кода,nextTickвсегда лучше, чемsetTimeoutВыполнить первым. То же самое в очереди, зачем вамnextTickБыть быстрее меня?

Начните вопрос, содержание полностью зависит от редактирования. (Работает под узлом, ответ дается в конце статьи.)

new Promise((resolve) => {
    console.log(1);
    
    process.nextTick(() => {
    	console.log(2);
    });
    
    resolve();
    
    process.nextTick(() => {
    	console.log(3);
    });
    
    console.log(4);
}).then(() => {
    console.log(5);
});

setTimeout(() => {
    console.log(6);
}, 0);

console.log(7);

Итак, каков именно порядок печати?

цикл событий

for(var i = 0; i < 5; i++){
    setTimeout(function after() {
        console.log(i);
    }, 0);
}

Все, должно быть, много раз видели этот вопрос, и ответ выпалил 5 5s. Зачем? Ответ: Закрытие. Почему происходят замыкания? отвечать:. . .

Все это должно начаться с того, что Нюва исправляет небо (почему бы вам не начать с Пангу, открывающего небо?).

Кратко объясните:

  1. Как правило, js выполняется сверху вниз и при выполнении помещается встек вызововin (Стек вызовов на рисунке).
  2. Затем для асинхронных событий (Ajax, таймеры и т. д.) браузер создаст таймер как часть веб-API и будет обрабатывать обратный отсчет для вас.
  3. Когда время истечет, он попадет в очередь задач (Callback Queue).
  4. Цикл событий берет функции из очереди обратного вызова и помещает их в стек вызовов.
  5. Начните с первого шага.

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

В приведенном выше примере, посколькуafter函数Цитируетсяiи будет вызываться в следующем цикле событий, в результате чегоiПамять нельзя освободить, и когда снова наступит следующий цикл, сырой рис превратится в кашу.iВсе сварено до 5.

По поводу памяти рекомендую статью, которую когда-то переводил вамКак работает JavaScript: управление памятью + как справиться с 4 распространенными утечками памяти. Также очень полезно для понимания замыканий.

Здесь я лишь кратко упомянул цикл обработки событий, более подробную информацию можно найти в ссылках в конце статьи.

Макрозадачи и микрозадачи

Среда размещения имеет только один цикл обработки событий, но может иметь несколько очередей задач. Очередь макрозадач (macro task) и очередь микрозадач (micro task) — две из них.

Каждый раз, когда возникает цикл событий,Сначала выполните задачу макросазадачи в очереди, затемповторно выполнять микрозаскизадачи в очереди.那么宏任务与微任务分别有哪些呢?

  • Задачи макроса: сценарий (глобальная задача), setTimeout, setInterval, setImmediate, ввод-вывод, рендеринг пользовательского интерфейса.
  • Микрозадачи: process.nextTick, Promise, Object.observer, MutationObserver.
new Promise((resolve) => {
    resolve();
}).then(() => {
    console.log(1);
});
setTimeout(() => {
    console.log(2);
}, 0);
console.log(3);

Согласно приведенному выше утверждению, он должен напечатать 3, 2, 1. Но на самом деле он печатает 3, 1, 2. Оказалось, что добавились микрозадачи типа process.nextTick и PromiseОчередь микрозадач текущего цикласреди. Следовательно, он будет выполняться позже, чем все задачи макроса в текущем цикле, и будет выполняться перед задачами макроса в следующем цикле.

process.nextTick и обещания

process.nextTick(() => {
    console.log(1); 
});
new Promise((resolve) => {
    resolve();
}).then(() => {
    console.log(2);
});
process.nextTick(() => {
    console.log(3); 
});

Почему я должен забрать эти две вещи? Проверьте это сами, потому что результат будет неожиданным.why?

К счастью, Интернет мощный. Нет ничего, чего Baidu не мог бы достичь, если есть, то погуглите.

«process.nextTick всегда больше, чем promise.then. Причина на самом деле очень проста… В Node _tickCallback вызывается после выполнения каждой задачи в TaskQueue, и этот _tickCallback, по сути, делает две вещи:

  1. Выполняются все задачи в nextTickQueue (максимальная длина 1e4, версия Node v6.9.1)
  2. После выполнения первого шага выполняется функция _runMicrotasks и часть микрозадачи (обратный вызов, зарегистрированный promise.then), поэтому очевидно, что process.nextTick > promise.then"

Мисс

VueсерединаnextTickЭто смешанное использование макро задач и микро задач, которые требуют ручного переключения. Наконец, правда вышла. Таймер: Хорошо, я прощу тебя за то, что опередить меня.

Так что же ответ на вопрос в начале этого? Или проверить это сами.

На бумаге, в конце концов, я чувствую себя мелким, я знаю об этом и должен это сделать.

А, мисс? какая мисс? ты прав

Я: Да ладно, это просто опечатка. дарезюме.

мне, что? Ваше удовольствие! Иди, иди, иди!

Арендодатель арестован отделкой.


setImmediate

В битве ордеров тоже есть странное явление.

setImmediate(() => {
    console.log(1);
});

setTimeout(() => {
    console.log(2);
}, 0);

Однако вы обнаружите, что иногда он печатает 1, 2, а иногда 2, 1. Почему ты ведешь себя как женщина?

Объяснение, данное на официальном сайте nodejs:

  • setImmediate(): предназначен для выполнения после выполнения текущей фазы задачи.
  • setTimeout(): задерживает выполнение кода.

Если он не выполняется в цикле ввода-вывода, то порядок его выполнения не определен.

Если выполняется в одном цикле ввода/вывода,setImmediateвсегда имеет приоритет надsetTimeoutвоплощать в жизнь.

const fs = require('fs');

fs.readFile(__filename, () => {
    setTimeout(() => {
        console.log('timeout');
    }, 0);
    setImmediate(() => {
        console.log('immediate');
    });
});

Всегда: печатать немедленно, а затем печатать по тайм-ауту.


использованная литература:

  1. Статья Учителя Жуань Ифэна ---Подробное объяснение механизма работы JavaScript: снова поговорим о цикле событий. (В этой статье есть ошибки. Рекомендуется попробовать каждый пример самостоятельно, просмотреть комментарии и проверить информацию.)
  2. Официальная документация NodeJs ---The Node.js Event Loop, Timers, and process.nextTick();
  3. Ответ о приоритете nextTick выше, чем обещание, можно найти в ответе Чжиху ---Как очередь Promise связана с очередью setTimeout?;
  4. Статья из серии «Как работает JavaScript» ---Как работает JavaScript: цикл событий и развитие асинхронного программирования + 5 способов улучшить программирование с помощью async/await);
  5. Асинхронный JavaScript, стек, цикл событий, очередь задач