Я пытался использовать Promise для тестирования различных способов использования Promise, но столкнулся с этими проблемами.
Я думал, что результат будет ждать 3000 мс, затем напечатать hello world 1, а затем непрерывно ждать 2000 мс для печати hello world 2. Однако после печати hello world 1 сразу появляется hello world 2.
Может ли кто-нибудь из экспертов объяснить мне, почему это произошло?
const helloWorld = new Promise((resolve, reject) => {
setTimeout(() => {
let temp = true;
if (temp) {
resolve("hello world 1");
} else {
reject("error occured");
}
}, 3000)
});
const helloWord2 = new Promise((resolve, reject) => {
setTimeout(() => {
let temp = true;
if (temp) {
resolve("hello world 2");
} else {
reject("error occured");
}
}, 2000)
});
helloWorld.then((value) => {
console.info(value);
helloWord2.then((value) => {
console.info(value);
})
});Что для вас означает «а затем непрерывно ждать 2000 мс»? Вы имеете в виду «а затем продолжать ждать 2000 мс»? Потому что слово «непрерывно» может означать «неоднократно без пауз», то есть будет ждать 2000 мс, запускаться helloWorld2, затем ждать еще 2000 мс и т. д.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема в том, что любая функция, которую вы вкладываете в себя, срабатывает сразу, а не тогда, когда на нее ссылаются. Объект обещания — это просто объект, который хранит либо результат, либо статус «пока нет значения», а не лямбда-выражение, которое может быть запущено по команде. Если вы измените свои функции тайм-аута, включив в них console.info, вы сможете увидеть истинное время выполнения этих функций.
const helloWorld = new Promise((resolve,reject) => {
setTimeout(() => {
let temp = true;
console.info("hello world 1");
if (temp){
resolve("hello world 1");
}else {
reject("error occured");
}
},3000)
});
const helloWord2 = new Promise((resolve,reject) => {
setTimeout(() => {
let temp = true;
console.info("hello world 2");
if (temp){
resolve("hello world 2");
}else{
reject("error occured");
}
},2000)
});
helloWorld.then((value) => {
console.info(value);
helloWord2.then((value) => {
console.info(value);
})
});Сначала вы увидите распечатку второго, так как у него более короткий тайм-аут. Тогда первый. Затем вы увидите выполнение блока Promise. Этот блок не будет выполняться до тех пор, пока не истечет первый тайм-аут Hello World, который к тому времени второе обещание Hello World уже разрешится в значение «hello world 2», что приведет к немедленной печати.
Один из способов решения этой проблемы — сохранить helloWorld2 как новую лямбду, возвращающую обещание, а не как обещание. Таким образом, тайм-аут helloWorld2 не будет срабатывать до тех пор, пока не будет разрешен helloWorld1, например:
const helloWorld = new Promise((resolve,reject) => {
setTimeout(() => {
let temp = true;
if (temp){
resolve("hello world 1");
}else {
reject("error occured");
}
},3000)
});
const helloWord2Lambda = () => { return new Promise((resolve,reject) => {
setTimeout(() => {
let temp = true;
if (temp){
resolve("hello world 2");
}else{
reject("error occured");
}
},2000)
})};
helloWorld.then((value) => {
console.info(value);
helloWord2Lambda().then((value) => {
console.info(value);
})
});Это очень хорошо объясняет проблему, но как ОП может ее исправить?
@RoryMcCrossan это улучшило бы ответ, но потребовало бы угадать, что на самом деле хочет сделать ОП.
Второй абзац в их вопросе, кажется, объясняет, что
@RoryMcCrossan хорошая мысль, спасибо. Я обновил.
Оба обещания helloworld и helloworld2 запускают свои таймеры одновременно.
Проще говоря, setTimeout внутри HW установлен на 3000 мс, а в HW2 — на 2000 мс. поэтому HW2 разрешился первым и сохранил данные «HW2», затем HW разрешился через 3000 мс и распечатал «HW1». вот в чем загвоздка: как только обещание helloworld разрешает выполнение блока «.then», печатается «hello world 1», поскольку «helloworld2» уже разрешено через 2000 мс, его результат сразу же доступен при выполнении блока «.then».
Поскольку время ожидания второго таймера меньше, чем у первого, оно будет разрешено уже при вызове вашего первого обратного вызова
.then(). Таким образом, когда вы выполняете вызов.then()внутри этого обратного вызова для второго таймера, этот обратный вызов.then()запускается немедленно, поскольку обещание будет выполнено.