Цепочка promises с promises внутри then()

Как вы связываетесь с таким сценарием?

api - это функция, которая возвращает обещание после HTTP-запроса. auth - это функция, которая возвращает обещание после ответа api, если разрешает api вызывается во второй раз, если не отклоняется auth.

Я пробовал это, но не только возвращаюсь к черту callback, это не работает.

function api(query) {
   return new Promise(function(resolve, reject) {
     //DO SOME STUFF AND SOMETIMES resolves...
   })
}

function auth() {
   return new Promise(function(resolve, reject) {
     api("/foo").then(function(asset1) {
        api("/bar").then(function(asset2) {
           resolve(asset2);
        }).catch(function() {
           reject();
        })
     }).catch(function(error) {
        reject();
     })

   })
}

Ответ 1

Насколько я понимаю, что вы пытаетесь сделать, следующий код также разрешит с помощью asset2. Кроме того, я предполагаю, что функция api выполняет http-запрос, поэтому вы можете использовать request-promise lib вместо преобразования обратного вызова api с помощью new Promise.

function api(query) {
   return new Promise(function(resolve, reject) {
     //DO SOME STUFF AND SOMETIMES resolves...
   })
}

function auth() {
   return api("/foo")
   .then(() => api("/bar"))
}

С этим вызывающим будет делать что-то вроде:

auth()
.then(asset2 => ...)
.catch(err => ...)

Если порядок вызова api не важен, как указано в комментарии @styfle, вы можете записать его с помощью Promise.all

function auth () {
  return Promise.all([
    api("/foo"),
    api("/bar")
  ])
}

Ответ 2

Я думаю, это должно помочь вам.

Просто наблюдение: метод then всегда возвращает обещание, основанное на предыдущем обещании. Если предыдущее обещание будет разрешено, оно передаст разрешенное значение к следующему обещанию. В противном случае он отправит ошибку методу catch.

function auth () {
  /*
    Since `then` already returns a new Promise, 
    you don't need to create a new Promise.
  */
  return api('/foo').then(function (asset1) {
    return api('/bar')
  })
}

/*
  So you can call auth:
*/

auth().then(function (asset2) {
  console.log('This is my asset2:', asset2)
}).catch(function (error) {
  console.error('Error', error)
})

Ответ 3

из Promises стандарт:

Если x является обещанием, примите его состояние [3.4]: Если x ожидает рассмотрения, обещание должно оставаться в ожидании до тех пор, пока x не будет выполнено или не будет отклонено. Если/когда х выполняется, выполняйте обещание с одинаковым значением. Если/когда х отклоняется, отвергайте обещание по той же причине.

Следующий пример печатает "finalVal":

let resolveP1 = null;

let p1 = new Promise(function(resolve, reject) {
    resolveP1 = resolve;
});

let p2 = new Promise(function(resolve, reject) {
    resolve(p1);
});

let p3 = p2.then(function(finalVal) {
    console.log(finalVal);
});

resolveP1('finalVal')

Ответ 4

Более чистый способ сделать это:

return myFirstPromise.then( (returnFromFirst) => {
    //Do something
    return secondPromise();
}).then( (returnFromSecond) => {
    //Do something
    return thirdPromise();
}).then( (returnFromThird) => {
    //All Done
}).catch( (e) =>{}
    console.error("SOMETHING WENT WRONG!!!");
);