зарегистрировать функцию потребления, используя .then - PullRequest
4 голосов
/ 20 мая 2019

Я новичок в JS, просто вопрос об обещании.Допустим, у нас есть следующий код:

const promise = new Promise((resolve, reject) => {
   ... //producing code
   resolve('This is my resolved data');
});

promise.then((data) => {
    console.log(data);
});

, поэтому при создании обещания эта функция исполнителя запускается автоматически.но что произойдет, если производящий код завершится очень быстро и до регистрации .then?не слишком ли поздно зарегистрироваться .then с нашей функцией завершения?

Ответы [ 4 ]

2 голосов
/ 20 мая 2019

Раздел 25.6.5.4.1 спецификации ECMA определяет поведение Promise.prototype.then s как:

[...]

Если обещание. [[PromiseState]] «ожидает», «ожидает», тогда

a.Добавьте executeReaction в качестве последнего элемента списка, который является обещанием. [[PromiseFulfillReactions]].

b.Добавьте rejectReaction в качестве последнего элемента списка, который является обещанием. [[PromiseRejectReactions]].

Иначе, если обещание. [[PromiseState]] "выполнено" "выполнено", затем

а.Пусть значение будет обещанием. [[PromiseResult]].

b.Выполнить EnqueueJob («PromiseJobs», «PromiseJobs», PromiseReactionJob, «executeReaction, value»).

Так что если вы присоединяете .then обратных вызовов к Promise (с именем «fullfillReaction»и "rejectReaction" здесь), и обещание еще не разрешено, обратные вызовы будут сохранены для последующего вызова (7a и b).

Если Обещание уже разрешено к тому времени (8), то оно непосредственно создаст задание для обратного вызова обратного вызова (8b), которое будет выполнено практически сразу (при следующей микротике).

не слишком ли поздно регистрироваться .then с нашей функцией завершения?

Нет, еще не слишком поздно.Обещание все еще знает значение, к которому оно разрешено, и будет вызывать обратный вызов .then с этим почти мгновенно.

Например:

  const promise = new Promise((resolve) => { // A promise gets created and is in "pending" state
   setTimeout(() => {
      resolve("value"); // the promise gets turned into "fullfilled" state, and "value" will be stored in the internal PromiseResult property of the promise
    }, 1000);
  });

  // By now the promise did not resolve yet, "callback" will be stored internally
  promise.then(function callback() { /*...*/ });

  // one second later, the promise fullfills and "callback" gets called. The promise is in "fullfilled" state

 setTimeout(() => { // another second later, this runs
   // As the promise is fullfilled already, "callback2" will directly put into a job onto the promise microtask queue
   promise.then(function callback2() {
     console.log("callback2 called");
   });
   // ...then the line below will run
   console.log("then attached after 2s");
   // at this point, synchronous code finishes, the call stack unwinds
   // the engine will continue working on the microtask queue
   // and voíla, it'll find the "callback2" callback, and will call it with the promises result (so it gets executed "nearly immeadiately")

 }, 2000);

¹: Это простогарантировать, что .then(...) всегда будет работать "асинхронно".Для простоты можно сказать, что функция запускается напрямую.

2 голосов
/ 20 мая 2019

Неважно, какова длительность задержки при разрешении / отклонении вызовов - в этом отношении она может быть мгновенной - но then и catch все еще работают, потому что это все еще Обещание:

const promise = new Promise((resolve, reject) => {
  resolve('This is my resolved data');
});

promise.then((data) => {
  console.log(data);
});
1 голос
/ 20 мая 2019

Это не имеет значения, так как Promise выполнит свои параметры успеха или неудачи метода, тогда, если затем он зарегистрирован на Promise.

in order to check:

var promise = new Promise((resolve, reject) => {
//    ... //producing code
   resolve('This is my resolved data');
});

// it will execute after a second
setTimeout(() => {
    promise.then((data) => {
       console.log(" asdasda", data);
    });
}, 1000)

promise.then((data) => {
    console.log("asdada asdasda", data);
});
0 голосов
/ 20 мая 2019

Javascript - это однопоточный язык с циклом обработки событий. Так что нет такого условия как

создание кода заканчивается очень быстро и до того, как зарегистрировано

Когда вы создаете обещание, вы создаете только объект. Этот объект обладает знанием состояния, разрешает и отвергает условия обещания. И разрешенное состояние обещания будет сохранено в том же объекте обещания. Это означает, что если вы зарегистрируете обработчик для обещания, который уже был разрешен, вы все равно получите разрешенное значение. Потому что он хранится в объекте обещания.

Проверьте пример ниже:

const promise = new Promise((resolve, reject) => {
    console.log('resolver function')
    setTimeout(() => resolve('This is my resolved data'), 1000)
});

console.log('just before adding promise handler')

promise.then((data) => {
    console.log(data);
});
    
setTimeout(() => {
    console.log('just before adding a late promise handler')

    promise.then((data) => {
        console.log(data);
    });
}, 2000)
...