Как сделать эту цепочку обещаний без async / await с помощью then, catch

  1. Мне нужно получить с сервера некоторую информацию.
  2. Если информация недействительна, я должен получить информацию, используя другой запрос к серверу.
  3. Если информация снова недействительна, я должен вернуть отклоненное обещание (ошибка)
  4. Если информация действительна на 2 или 3 шагах, я должен сохранить ее и вернуть обработанное обещание в вызывающий код.

Я сделал это с помощью async / await. Но я не могу понять, как это сделать, используя блоки then и catch.

Мой код:

this.loadSettingReport()
  .then(() => {
    console.log("Success!")
  })
  .catch((error) => {
    console.log("Promise worked with Error")
    console.log(error)
  })

//...

async loadSettingReport() {
  console.log("SettingReport - Company")
  let response = await findAllSettingsReports(this.$axios, /*someParameters*/) //request via axios - return promise
  let data = response.data
  console.log(data)
  if(data.length === 0) {
    console.log("SettingReport - Common")
    response = await findAllSettingsReports(this.$axios, /*other someParameters*/) //request via axios  - return promise
    data = response.data
    if (data.length === 0) {
      console.log("SettingReport - NotFound")
      throw new Error("SettingReport - NotFound")
    }
  }
  //Do something...
},

//...

export const findAllSettingsReports = function($axios, params = {}){
  return $axios.get(url, isEmpty(params) ? {} : { params: params })
}

ОБНОВЛЕНИЕ. Мой последний вариант:

loadSettingReport() {
   return findAllSettingsReports(this.$axios, {variant: "ID", rows: true, search: "common:false,company.id:"+this.company.id + ",typeReport.id:" + this.typeReportId})
      .then(response => {
         if(response.data.length == 0) {
            return findAllSettingsReports(this.$axios, {variant: "ID",  rows: true, search: "common:true,typeReport.id:" + this.typeReportId})
         }
         return response
      })
      .then(response => {
         if(response.data.length == 0) {
            throw new Error("Настройка отчетов не найдена")
         }
         this.setting = response.data[0]
         return response.data[0]
      })
}

person Alexander Lopatin    schedule 08.02.2020    source источник
comment
Представьте, что блок под try находится под then и под catch, как под обещанием, в сравнительном мысленном образе, вот так!   -  person cybercoder    schedule 08.02.2020


Ответы (2)


За счет передачи успешного результата на шаге цепочки обещаний вы можете заменить функцию async чем-то вроде

const loadSettingReport = () => {
    return findAllSettingsReports(this.$axios( /*someParameters*/ ))
       .then (response => {
           if( response.data) {
              return response;
           }
           return findAllSettingsReports(this.$axios( /*other Parameters*/ ))
       })
       .then (response => {
           if( !response.data) {
               console.log("SettingReport - NotFound")
               throw new Error("SettingReport - NotFound")
           }

           // .... do something with response 

           return something;
       });
};

Возвращенное обещание выполняется со значением return something или отклоняется с ошибкой.

person traktor    schedule 08.02.2020

Общее правило - поменять все

someVar = await somePromise;
// more lines

в

return somePromise.then((someVar) => {
  // more lines
});

Вы пытаетесь сделать две разные вещи, это выглядит так:

  • Получить данные (повторить попытку один раз)

  • Сделайте что-нибудь с данными

Чтобы они не повторялись и чтобы они хорошо сочетались с синтаксисом .then, поместите их в отдельные функции:

loadSettingReport(retries = 1) {
  return findAllSettingsReports(this.$axios, /*someParameters*/).then((response) => {
    if(response.data.length === 0) {
      if (retries === 0) {
        throw new Error("SettingReport - NotFound");
      }
      return this.loadSettingReport(retries - 1);
    }
    return response;
  });
},
processSettingsReport(response) {
  // do something
}

а также

this.loadSettingReport()
  .then(response => this.processSettingsReport(response))
  .catch((error) => {
    console.log("Promise worked with Error")
    console.log(error)
  })
person CertainPerformance    schedule 08.02.2020
comment
Первая версия (после такой :) не выполняет строку // do something, если есть начальная ошибка. Версия с повторными попытками выглядит хорошо. - person traktor; 08.02.2020
comment
Логика такая же, как в вашем коде. Как и в исходном коде, в случае ошибки вызов loadSettingReport будет отклонен без продолжения выполнения другого кода ниже в функции. Если вы этого не хотите, поставьте .catch на вызовы findAllSettingsReports. - person CertainPerformance; 08.02.2020
comment
Код сразу после Like this: возвращает обещание вызывающему loadSettingReport, которое будет выполнено с undefined, если вторая попытка будет успешной, в отличие от опубликованной функции async или моего кода. - person traktor; 08.02.2020
comment
Если, конечно, do something` возвращает undefined, тогда вам просто нужны побочные эффекты от запуска его кода. - person traktor; 08.02.2020
comment
Большое спасибо! Собственно, это Vue.js. Я не упомянул об этом, извините. // do something - это просто сохранение полученных данных. - person Alexander Lopatin; 10.02.2020