Это фрагмент из файла модульного теста, в котором используется jest. Функция синтаксического анализа возвращает обещание после завершения синтаксического анализа... Но я не могу понять использование этого логического флага (completedAsyncDummyTask).
it("parse is a promise that resolves with parser output", async () => {
const parser = new Parser();
let completedAsyncDummyTask = false;
setTimeout(() => {
completedAsyncDummyTask = true;
}, 0);
...
const test = await parser.parse(path.resolve(__dirname, "file.xyz"));
expect(completedAsyncDummyTask).toBe(true);
...
});
Любые идеи?
Заранее спасибо.
Отвечает ли это на ваш вопрос? Почему setTimeout(fn, 0) иногда полезен?
@CristianTraìna - я думаю, что это больше о взаимодействии между выполнением обещаний и взаимодействием между используемой для него очередью микрозадач и очередью макрозадач, используемой для обратных вызовов таймера.
Я не могу представить, какова была бы цель теста. Я могу сказать вам, что он делает, но не почему.
Он проверяет, выполнил ли процесс parser.parse(path.resolve(__dirname, "file.xyz"))
свое обещание, разрешив хотя бы один цикл через основную («макро») очередь задач, а не просто выполняя всю свою работу в очереди микрозадач, используемой при выполнении обещания.
Если обещание выполняется сразу, у основной очереди задач никогда не будет возможности запуститься до того, как запустится код, использующий await
:
(async () => {
setTimeout(() => {
console.info("This comes second because it queues a macrotask");
}, 0);
await Promise.resolve();
console.info("This comes first because the promise fulfillment never allowed the macro task queue to be processed.");
})();
Но если это не так, основная очередь задач может быть обработана хотя бы один раз, что дает этому обратному вызову таймера возможность установить переменную.
Наличие теста говорит о том, что в приложении есть какой-то код, основанный на таком поведении, что было бы довольно странно. Еще более странно, что нет никакого комментария, объясняющего столь малопонятный тест.
У вас может возникнуть соблазн подумать, что, поскольку Promise.resolve
возвращает выполненное обещание, await
вообще ничего не делает, и этот код просто выполняется синхронно. Это неправда, даже ожидание выполненного обещания включает задержку последующего кода в наименее до тех пор, пока очередь микрозадач не зациклится, как мы можем видеть здесь:
let run = true;
let ticks = 0;
(async () => {
while (run) {
await Promise.resolve();
++ticks;
}
})();
(async () => {
setTimeout(() => {
console.info(`This comes second because it queues a macrotask`);
}, 0);
console.info(`Before: ticks = ${ticks}`);
await Promise.resolve();
console.info(`After: ticks = ${ticks}`);
console.info("This comes first because the promise fulfillment never allowed the macro task queue to be processed.");
run = false;
})();
Я согласен с такой интерпретацией, вероятно, автор хотел проверить, действительно ли parse
было async
. Если бы код parse
был похож на return Promise.resolve(parsedObject)
, тест провалился бы. Мы можем просто подумать, в каких сценариях тест не проходит, и попытаться выяснить,
@CristianTraìna - Да, или он полностью полагался только на цепочку уже выполненных обещаний. Странный тест однако. :-)
Это... тест интересный. Я понимаю, почему вы спросили об этом.