Страницы

Поиск по вопросам

среда, 5 февраля 2020 г.

Работа resolve в promise

#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

Комментариев нет:

Отправить комментарий