Является ли создание Promise синхронным? - PullRequest
2 голосов
/ 04 апреля 2019

Мне нужно написать функцию, которая выполняет два цепных HTTP-вызова и воздействует на результат, как только будут получены результаты второго вызова.

Подход, который я думал, сработает:

function getdata() {
  return fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(r => r.json())
    .then(r => fetch(`https://jsonplaceholder.typicode.com/todos/2`)
      .then(s => s.json())
    )
}
let m = getdata()
m.then(x => console.log(JSON.stringify(x)))

Это работает нормально, вывод на консоль соответствует ожидаемому.

Затем я перенес эту идею на свой реальный вызов, главное отличие в том, что HTTPS-вызовы медленные. Чтобы отобразить фактическую ошибку в коде, рассмотрим небольшой вариант кода выше (с добавлением некоторой регистрации)

function getdata() {
  return fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(r => r.json())
    .then(r => fetch(`https://jsonplaceholder.typicode.com/todos/2`)
      .then(s => {
        console.log(s)
        s.json()
      })
    )
}
let m = getdata()
m.then(x => console.log(x))

Вывод на консоль (из моего реального кода) похож на

11:36:56.388 undefined
11:36:56.456 filter-sentinels.js:42 Response {type: "cors", url: …}

Подробнее:

  • первый undefined от console.log(x)
  • вторая строка от console.log(s)

Казалось бы, Обещание разрешается во второй строке, которая идет после первой. Это нормально, для этого и есть обещания.

Что я не понимаю, так это , почему .then() в m.then(x => console.log(x) )) выполняется, когда обещание еще не выполнено?

Примечание к заголовку: что я действительно хочу понять, так это то, могу ли я рассматривать генерируемый Обещание (let m = ...) как нечто синхронное - в том смысле, что я могу безопасно применить then() к нему и что происходит в then() произойдет, когда известная информация известна (возвращен HTTP-вызов).

1 Ответ

3 голосов
/ 04 апреля 2019

Проблема в том, что в несетном fetch есть одно Обещание, которое не приковано цепью к внешним, s.json():

.then(s => {
  console.log(s)
  s.json() // <---- This is not being returned; the Promise chain will resolve to undefined
})

Вы просто объявляете s.json() Обещание, но не возвращаете его или не используете вообще, поэтому все getdata() Обещание разрешается до undefined, как только ответ с /totos/2 возвращается.

Возвращает последний вложенный .json() вызов, и он работает как положено:

function getdata() {
  return fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(r => r.json())
    .then(r => fetch(`https://jsonplaceholder.typicode.com/todos/2`)
      .then(s => {
        console.log(s)
        return s.json()
      })
    )
}
m = getdata()
m.then(x => console.log(x) )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...