Не могу установитьTimeout с помощью Promise

Я пытался использовать 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);
  })
});

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

Pointy 02.08.2024 17:22

Что для вас означает «а затем непрерывно ждать 2000 мс»? Вы имеете в виду «а затем продолжать ждать 2000 мс»? Потому что слово «непрерывно» может означать «неоднократно без пауз», то есть будет ждать 2000 мс, запускаться helloWorld2, затем ждать еще 2000 мс и т. д.

Heretic Monkey 02.08.2024 17:44
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема в том, что любая функция, которую вы вкладываете в себя, срабатывает сразу, а не тогда, когда на нее ссылаются. Объект обещания — это просто объект, который хранит либо результат, либо статус «пока нет значения», а не лямбда-выражение, которое может быть запущено по команде. Если вы измените свои функции тайм-аута, включив в них 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);
    })
});

Это очень хорошо объясняет проблему, но как ОП может ее исправить?

Rory McCrossan 02.08.2024 17:30

@RoryMcCrossan это улучшило бы ответ, но потребовало бы угадать, что на самом деле хочет сделать ОП.

Pointy 02.08.2024 17:33

Второй абзац в их вопросе, кажется, объясняет, что

Rory McCrossan 02.08.2024 17:34

@RoryMcCrossan хорошая мысль, спасибо. Я обновил.

Kaden Keep 02.08.2024 17:44

Оба обещания helloworld и helloworld2 запускают свои таймеры одновременно.

Проще говоря, setTimeout внутри HW установлен на 3000 мс, а в HW2 — на 2000 мс. поэтому HW2 разрешился первым и сохранил данные «HW2», затем HW разрешился через 3000 мс и распечатал «HW1». вот в чем загвоздка: как только обещание helloworld разрешает выполнение блока «.then», печатается «hello world 1», поскольку «helloworld2» уже разрешено через 2000 мс, его результат сразу же доступен при выполнении блока «.then».

Другие вопросы по теме