JS: Комплексная цепочка Promise - PullRequest
0 голосов
/ 09 января 2019

При попытке связать сложные вызовы функций с обещаниями и обратными вызовами я столкнулся с небольшой проблемой.

У меня есть основная функция, которая вызывает подпрограммы. В этих подпрограммах выполняются вызовы API.

Например:

function handle(){
    new Promise(function(resolve, reject){
        let result = doAPICall1()
        if (result === true) resolve(true);
        reject(JSON.stringify(result))
    }).then(function(){
        let result = doAPICall2()
        if (result === true) return true
        throw new Error(JSON.stringify(result))
    }).catch(error){
        console.error(JSON.stringify(error))
    }
}
function doAPICall1(){
    axios.get('...').then(function(){
        return true
    }).catch(function(error){
        return error
    })
}

function doAPICall2(){
    axios.get('...').then(function(){
        return true
    }).catch(function(error){
        return error
    })
}

Но когда я выполню этот пример, doAPICall2 будет выполнен, пока doAPICall1 все еще работает.
Это происходит только при длительных звонках.

Кто-нибудь может дать мне подсказку? Спасибо!

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Вы перестарались вручную со многими вещами, которые Promises уже сделали для вас: axios.get уже возвращает Обещание, поэтому нет смысла возвращать ответ при разрешении и возвращать false при отклонении. Обработчик catch в конце цепочки Promise уже обрабатывает все ошибки, которые могут возникнуть во время цепочки, поэтому вам не нужно catch каждое обещание.

Я бы сделал что-то вроде:

function doAPICall1(){
  return axios.get('...');
}

function doAPICall2(){
  return axios.get('...');
}

function handle(){
  // in case you would use the api calls results.
  let firstResult = null;
  let secondResult = null;
  return doAPICall1()
  .then(res => {firstResult = res})
  .then(() => doAPICall2())
  .then(res => {
    secondResult = res;
    return []
   })
}

Полагаю, вы будете использовать результаты вызовов API для чего-то. С помощью приведенного выше кода вы можете использовать функцию handle() следующим образом:

function someSortOfController(){
  handle().then(results => {
    console.log(results[0]); // first api call result
    console.log(results[1]); // second api call result
  })
  .catch(err => {
    // here you will find any error, either it fires from the first api call or from the second.
    // there is *almomst* no point on catch before
    console.log(err);
  })
}

Там вы получите доступ к любой ошибке, либо от первого вызова API, либо от второго. (И из-за того, как работает Promises, если первый вызов не удался, второй не сработает).

Для более детального контроля ошибок, вы можете захотеть перехватывать после каждого Promise, чтобы вы могли добавить несколько дополнительных журналов, например:

function doAPICall1(){
  return axios.get('...')
  .catch(err => {
    console.log('the error came from the first call');
    throw err;
  });
}

function doAPICall2(){
  return axios.get('...')
  .catch(err => {
    console.log('the error came from the second call');
    throw err;
  });
}

Теперь, если первый вызов API завершится неудачно, все будет работать как прежде (так как вы снова выдаете ошибку в catch), но у вас больше контроля над обработкой ошибок (возможно, ошибка, возвращающаяся из вызовов API, не совсем понятно и вам нужен такой механизм управления).

Ответственность

Этот ответ не отвечает, почему ваш код действует так, как он. Однако в вашем коде так много неправильного, поэтому я думаю, что предоставить вам пример использования Promises более ценно.

0 голосов
/ 09 января 2019

Не беспокойтесь и найдите время, чтобы лучше понять Обещания. В приведенном ниже примере кода функция doAPICall возвращает Promise, который разрешает значение, а не само значение.


    function handle() {
        doAPICall().then(result => {
            //do something with the result
        }).catch(error => {
            //catch failed API call
            console.error(error)
        }) 
    }

    doAPICall() {
        // this returns a Promise
        return axios.get(...)
    }
...