#javascript #ajax #promise
Есть такой код, один аспект которого мне не понятен: 'use strict'; let promise = new Promise((resolve, reject) => { resolve("Промис завершился"); console.log("Промис ждет, пока я появлюсь"); }); promise .then( result => console.log("Fulfilled: " + result), error => console.log("Rejected: " + error) ); Собственно, не понятно то, что алерт в функции-конструкторе вообще отрабатывает своё и появляется. И сразу же за ним (это прям вообще не понятно - почему за ним?) появляется "промис завершился". Не понятно по какому принципу работает resolve(), то есть передается управление обработчику .then. Я много раз видел, когда resolve() помещали конкретно внутрь обработчика onload (для ajax запросов, например), который сам по себе говорит о завершенности выполнения вопроса. А получается, что resolve() можно запихнуть хоть с самого начала и код ниже всё равно отработает. Да, конечно, в случае с ajax можно ожидать отклонение запроса сервером, поэтому нужно использовать resolve() в случае успеха, а reject() в случае ошибки. Помогите разобраться.
Ответы
Ответ 1
В JS остановить функцию может только или return, ошибка или её конец. Почитать. В ожидании используется некий асинхронный подход (иначе не вышло бы отлавливать асинхронные операции, Ваш КО): при разрешении обещания, коллбэк встаёт в очередь до завершения ожидающего кода в функции и только потом вызывается. Если Вам этого не нужно, используйте return: return resolve();.Ответ 2
Промис(обещание) сам по себе никого не ждёт. Просто у вас есть возможность обрабатывать как синхронный, так и асинхронный код. Созданный Promise исполняется сразу же, синхронно(на самом деле это зависит от реализации), а своих подписчиков(then) уведомляет на следующем такте event-loop. Давайте рассмотрим его поведение на примере: 'use strict'; let promise = new Promise((resolve, reject) => { resolve("Промис завершился"); console.log("1. Promise created"); }); console.log('2. After creation'); promise .then( result => console.log("3. Resolved: " + result), error => console.log("Rejected: " + error) ); console.log('2.5 функция в .then тем не менее будет вызвана позже'); Как видите, Promise при создании сразу(синхронно) запустил свой executor, но обработчик в then будет вызван на следующей итерации eventLoop. Пример внутренней реализации(очень урезанной): function Thennable(executor) { let thenList = []; let state = 0; // 1 - resolved, 2 - rejected let value = null; // executor вызывается сразу же, синхронно executor( res => { thenList.forEach(then => // обработчики вызываются асинхронно. setTimeout(() => then[0](res))); state = 1; value = res; }, error => { thenList.forEach(then => setTimeout(() => then[1](error)) ); state = 2; value = error; } ); this.then = (onResolve, onReject) => { if (state == 0) {// ещё не обработано, добавим в очередь ожидающих thenList.push([onResolve, onReject]); } else if (state == 1) { // resolved onResolve(value); } else if (state == 2) { // rejected onReject(value); } // return new Thennable(...) }; } let p = new Thennable((ok, fail) => { ok('resolved'); console.log('1 created'); }); console.log('2 after create'); p.then(res => console.log(3, res))Ответ 3
resolve() обычная коллбэк функция, вызов который говорит промису перейти в выполненое состояние. resolve() не останавливает выполнение функции внутри промиса.Ответ 4
Приведу цитату из статьи, что бы не ошибиться: Согласно стандарту, у объекта new Promise(executor) при создании есть четыре внутренних свойства: PromiseState – состояние, вначале «pending». PromiseResult – результат, при создании значения нет. PromiseFulfillReactions – список функций-обработчиков успешного выполнения. PromiseRejectReactions – список функций-обработчиков ошибки. Когда функция-executor вызывает reject или resolve, то PromiseState становится "resolved" или "rejected", а все функции-обработчики из соответствующего списка перемещаются в специальную системную очередь "PromiseJobs". Эта очередь автоматически выполняется, когда интерпретатору «нечего делать». То есть resolve не сразу вызывает функцию, а ждет окончания функции-executor, которую передали при создании promise-a
Комментариев нет:
Отправить комментарий