Почему последний .затем работает в цепочке обещаний

#javascript

Вопрос:

Я новичок в JavaScript. В следующем коде я ничего не вернул из .затем метод. Итак, как и ожидалось .тогда ничего не получится. Мой вопрос в том, почему последний .затем (синий цвет) работайте вместо первого .затем (красный цвет).

 let bodyBgChange = (color, delay) => {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            document.body.style.backgroundColor = color
            resolve()
        }, delay)
        
    })
}

bodyBgChange('green',1000)
    .then(()=>{ 
        bodyBgChange('red', 1000)
    })
    .then(()=>{
        bodyBgChange('yellow', 1000)
    })
    .then(()=>{
        bodyBgChange('pink', 1000)
    })
    .then(()=>{
        bodyBgChange('blue', 1000)
    })
     

Комментарии:

1. Он .then() всегда будет возвращать обещание, однако, если вы вернете синхронное значение, оно просто отправит его в очередь микрозадач как можно скорее, как есть. Не используя никаких return инструкций, вы заставляете .then() возвращать обещанное синхронное значение, которое является undefined . Поэтому, когда вы размещаете несколько заказов на покраску, все они складываются в очередь анимационных кадров и окрашиваются каждые 1/60 секунды (~17 мс) одновременно, поэтому вы видите только последний.

Ответ №1:

Вы забыли return или используете неявное возвращение функции стрелки

 let bodyBgChange = (color, delay) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      document.body.style.backgroundColor = color
      resolve()
    }, delay)

  })
}

bodyBgChange('green', 1000)
  .then(() => {
    return bodyBgChange('red', 1000)
  })
  .then(() => {
    return bodyBgChange('yellow', 1000)
  })
  .then(() => {
    return bodyBgChange('pink', 1000)
  })
  .then(() => {
    return bodyBgChange('blue', 1000)
  }) 

Комментарии:

1. Привет, спасибо за ваш ответ. Я намеренно опустил ключевое слово return. Мой вопрос был в том, почему последний . затем работает без ключевого слова return. Не должен ли первый .затем работать, если я не использую ключевое слово return?

Ответ №2:

Он просто запускается каждый блок, если не происходит ошибок.

Вот в чем волшебство: функция then() возвращает новое обещание, отличное от исходного:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

Действительно черная магия.

Ответ №3:

Вы неправильно then меня поняли.

Каждый из ваших then крючков вызывается независимо от того, возвращают ли они значение. И, видя, что у каждого из них установлен один и тот же таймер, будет казаться, что «работает»только последний крючок. Возвращаемые значения в вашем крючке then передадут это значение следующему крючку then, что должно привести к поведению, которого вы ожидали в этом случае.

 let bodyBgChange = (color, delay) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      document.body.style.backgroundColor = color
      resolve()
    }, delay)
  })
}

bodyBgChange('green', 1000)
  .then(() => {
    return bodyBgChange('red', 1000)
  })
  .then(() => {
    return bodyBgChange('yellow', 1000)
  })
  .then(() => {
    return bodyBgChange('pink', 1000)
  })
  .then(() => {
    return 'foo'
  })
  .then((val) => {
    // val === 'foo'
  }
 

Комментарии:

1. Теперь понятно. Большое спасибо за ваше подробное объяснение.

2. Нет проблем, рад помочь 🙂