Шутка: ожидание против setImmediate против useFakeTimers против нового обещания (setImmediate) - PullRequest
4 голосов
/ 17 июня 2020

Далее следует тест Jest на TypeScript. Мне интересно, зачем нужен setImmediate ().

Первый пример - это работающий тест. Затем я пробовал разные вещи, которые не работают. Я не понимаю, что происходит. Подпись для pubsub.publi sh: (method) PubSub.publish(triggerName: string, payload: any): Promise<void>

  test.only('subscriptions', async () => {
    const document = parse(`
      subscription {
        create 
      }
    `)

    const sub = <AsyncIterator<ExecutionResult>>await subscribe(schema, document);

    expect(sub.next).toBeDefined()

    // setInterval and process.nextTick also work here:
    setImmediate(() => pubsub.publish('CREATE_ONE', { create: "FLUM!" }))  // this works


    const { value: { errors, data } } = await sub.next()

    expect(errors).toBeUndefined()
    expect(data).toBeDefined()
    expect(data.create).toBe('FLUM!')
  }, 10000)

Итак, это другие вещи, которые я пробовал, некоторые после поиска ответов на похожие проблемы. Все эти попытки терпят неудачу с исключением тайм-аута в тесте:



  test.only('subscriptions', async () => {
  // attempt #1: jest.useFakeTimers()

    const document = parse(`
      subscription {
        create 
      }
    `)

    const sub = <AsyncIterator<ExecutionResult>>await subscribe(schema, document);

    expect(sub.next).toBeDefined()

    // #1, cont: 
    // pubsub.publish('CREATE_ONE', { create: "FLUM!" })
    // or...
    // await pubsub.publish('CREATE_ONE', { create: "FLUM!" })
    // this works, though, like in previous test, but with fake timers:
    // setImmediate(() => pubsub.publish('CREATE_ONE', { create: "FLUM!" }))


    // attempt #2:
    // await pubsub.publish('CREATE_ONE', { create: "FLUM!" })

    // attempt #3:
    // pubsub.publish('CREATE_ONE', { create: "FLUM!" })
    // await new Promise(setImmediate)

    // attempt #3a (variant):
    // await new Promise((resolve) => setImmediate(resolve));

    const { value: { errors, data } } = await sub.next()

    expect(errors).toBeUndefined()
    expect(data).toBeDefined()
    expect(data.create).toBe('FLUM!')
  }, 10000)

Я понимаю, что setImmediate помещает функцию в событие l oop, которая будет выполняться сразу после любых ожидающих событий ввода-вывода. Я не уверен, зачем это нужно, потому что pubsub.publi sh () возвращает обещание, которое можно обработать с помощью await , но в этом случае происходит следующее: await sub.next () никогда не вызывается.

Я думаю, что в pubsub.publi sh () выполняется вызов setInterval, а setImmediate ожидает завершения любых ожидающих событий setInterval (мое понимание этого нечеткое). Попытки 3 и 3a - это механизмы, которые я нашел в другом месте, но в данном случае они, похоже, не работают.

Вопрос: почему этот тест требует прохождения setImmediate?

1 Ответ

0 голосов
/ 27 июня 2020

Итак, мое замешательство связано с тем, что setImmediate делает и чего не делает. Вот что происходит:

    // setInterval and process.nextTick also work here:
    setImmediate(() => pubsub.publish('CREATE_ONE', { create: "FLUM!" })) 
    const { value: { errors, data } } = await sub.next()

Без setImmediate () событие publi sh отправляется до вызова sub.next (), поэтому оно не фиксируется. Вы могли подумать, что setImmediate (или process.nextTick) вызовет немедленное выполнение функции publi sh, но нет. Вместо этого setImmediate задерживает вызов publi sh на время, достаточное для выполнения sub.next ().

Теперь я собираюсь прочитать несколько исправлений о том, как на самом деле работают setImmediate и process.nextTick.

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