Могу ли я рассчитывать на последующие не связанные цепочки заказы? - PullRequest
0 голосов
/ 29 августа 2018

Известно, что можно объединить несколько Обещаний в цепочку и таким образом вызывать onFulfilled обратных вызовов ровно один за другим (несмотря на то, что они будут асинхронными друг от друга):

Promise.resolve()
    .then(() => {
       console.log("i will be the first one");     
    })
    .then(() => {
       console.log("i will be the second one");  // definetely second
    })
;

Но как быть с последующими обещаниями, не связанными цепочкой? Простейший пример:

Promise.resolve()
   .then(() => console.log("i will be the first one"))
;
Promise.resolve()
   .then(() => console.log("i will be the second one"))  // sure?
;

По моему наивному мнению, обратные вызовы Promises работают через очередь событий (примерно так же, как событие таймера внутри setTimeout) и таким образом сначала Promise.resolve() помещают свое событие в очередь перед тем, как это сделает второй, поэтому первый обратный вызов будет вызываться раньше. второй.

Но я не уверен, что есть какие-либо гарантии по этому поводу. Могу ли я рассчитывать на это или это асинхронное лото? Кто-нибудь знает, что спецификации говорят об этом?

UPDATE

Некоторые из вас заметили, что самый простой пример бесполезен, поэтому я хочу объяснить мою первоначальную проблему.

У меня есть класс, который лениво инициализирует экземпляр другого класса и предоставляет метод get для размещенного экземпляра:

class Lazy {

    /** @param {Class} T */
    constructor(T) { }

    /** @returns {Promise.<T>} */
    instance() { 
       // there will be complex async initialization at first call
       // and Promise.resolve() at following calls
    }
}

class Foo {
   on() { }
   off() { }
}

/** @type {Lazy.<Foo>} */
let foo = new Lazy(Foo);

foo.instance().then((i) => i.on());
foo.instance().then((i) => i.off());

Последние две строки раскрывают мою проблему - трудно работать с экземпляром Foo таким образом, когда я не уверен, что on() будет вызван раньше off().

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Ваш актуальный вопрос:

Последние две строки раскрывают мою проблему - трудно работать с экземпляром Foo таким образом, когда я не уверен, что on () будет вызываться раньше off ().

Вы не должны полагаться на это поведение, вместо этого вы должны await получить экземпляр и затем кэшировать его:

async function withInstance() {
  let instance = await foo.instance();    
  await instance.on();
  await instance.off(); // guaranteed to be called after `.on`.
}

Что вы спросили

Вы можете положиться на порядок выполнения Job с.

Когда добавляется обещание then, это EnqueueJob в спецификации. Цитирование Задания и очереди заданий :

Записи PendingJob из одной очереди заданий всегда инициируются в порядке FIFO.

Обратите внимание, что эта гарантия не действует, если у вас несколько контекстов (например, разные обещания между iframes или работниками).

Тем не менее, настоятельно не рекомендуется полагаться на такой порядок исполнения.

0 голосов
/ 29 августа 2018

Обратные вызовы Promises работают через очередь событий

Это не правда. Обратные вызовы работают в порядке возврата. Порядок, когда вы инициируете операцию, не важен, именно порядок, в котором они возвращают , определяет, какая операция будет обработана первой.

В вашем примере, если ваша «первая» асинхронная операция вернется дольше, чем ваша «вторая» асинхронная операция, тогда «вторая» then будет обработана первой.

Очевидно, существует множество переменных, определяющих, сколько времени займет выполнение этой операции. Скорость сети, нагрузка на сервер (или любой другой асинхронный сервис, который вы используете), реализация браузером механизма обещаний и т. Д. И т. Д. Итак, вы должны предположить, что не знаете, когда они будут обработаны .

Чтобы избежать условий гонки, если вам нужно, чтобы что-то было в определенном порядке, используйте обратные вызовы / .then / await / etc, чтобы убедиться, что они работают в этом порядке. Вы не можете полагаться на порядок, который вы называете операцией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...