JavaScript Promises. Chaining
Людям, хорошо знающим JS, вряд ли будет интересно, но я был бы благодарен за «review», ибо на js я автоматизирую не больше полугода и могу что-то упустить...
Тех, кому интересна данная тема — прошу вниз )
У нас на проекте было некое недопонимание в плане того, что иногда инструкция в зене не ждёт выполнения предыдущего зена. Частный случай:
promise .then(browser.wait(time))В этом случае мы не ждём в том месте где хотели бы ждать. Почему так происходит... Немного теории: JS — синхронный! У него есть Call Stack и Callback Queue. В Callback Queue падает весь «асинхронный» код, т.е. колбеки или промисы (те же колбеки, только в профиль). Всё остальное идёт в Call Stack. Call Stack всегда выполняется первым. Когда там пусто — выполняются задачи из Callback Queue.
Теперь рассмотрим другой пример:
var promise = new Promise(function(resolve, reject) { resolve(1); }); function logger(message) { console.log(message); } promise .then(logger) .then(logger(2)) .then(() => logger(3));В аутпуте будет сначала 2, потом 1 и 3. Почему так происходит:
then — функция, которая опционально принимает 2 колбека —
.then(logger) === .then(whateverPromiseReturns => logger(whateverPromiseReturns))Т.е. logger(1), который пойдёт в Callback Queue
Теперь всё логично, в очереди у нас logger(2), а в Callback Queue: logger(1) и logger(3). Call Stack выполняется первым, поэтому мы видим 2 в начале аутпута, после выполняется Callback Queue, который пишет 1 и 3.
UPD3:
JS даёт возможность вызывать в зене функцию, а не передавать ей колбек. Это сделано для того, чтобы вызвать функцию, которая вернёт функцию с замкнутыми переменными или контекстом. Но нужно быть осторожными, чтоб не получилось так:
var promise = new Promise(function(resolve, reject) { reject(); }); promise .then(console.log(1), () => console.log(2), console.log(3))Вернёт 1 3 2...
Прошу в комменты )
UPD: Хороший пример из комментов, который более наглядно показывает проблему:
const promise = new Promise((resolve, reject) => resolve(1)); const logger = (mes) => { console.log("Side effect: ", mes); return (arg) => { console.log("Resolved: ", arg); } } promise .then(logger(1)) .then(logger(2)) .then(logger(3))
UPD2: Очень классное видео про event loop, call stack и callback queue. Плюс описана разница между колбеками в array helpers и async callback.
latentflip.com/loupe
Спасибо, Alex Dubovyk!
105 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів