Búsqueda de sitios web

javascript - Devolver éxito al manejar un error en una promesa


Tengo una promesa que maneja una solicitud HTTP realizada a través de una API web:

promise = promise.then(r => { 
    // ...
  }, error => {
    if (error.status == 404) {
      // Here I can fix an error and continue properly
    } else {
      // Here the error should be propagated further in the promise
    }
}

// later in the code:
promise.catch(r => { /* More error handling */ } );

Más adelante en el código, esta promesa se encadena a más comprobaciones de errores.

En caso de un error 404, en realidad puedo "arreglar" un problema, y no quiero que se active el otro manejador. Preferiría hacer que la promesa sea un éxito en este caso. ¿Cómo puedo hacer eso?

Un poco más de código para explicar mi caso con más detalle:

refresh() {
  this.refreshAsync().catch(r => {
     // Show error to the user.
     notifications.showError("Unexpected error happened");
  });
}

async refreshAsync() {
  // Here goes a lot of vue-resource calls to gather the necessary data for a view. They are chained with `await`. Only one of them:
  await this.$http.get(url).then(r => {
    this.data = r.data;
  }, error => {
    // 404 is actually a legit response for API to return, so the user notification above should not be shown
    if (error.status == 404) {
      // handle successfully
    } else {
      // propagate an error, so the handler above could show a warning to the user.
    }

  });

}

Respuesta #1

Simplemente puedes devolver un rechazar/resolver

if(error.status == 404)
    return Promise.resolve('OK')
else
    return Promise.reject('fail')

Hice un ejemplo mostrando cómo funciona esto, solo para este caso:

httpRequest = function () {
  return new Promise(function (res, rej) {
    let status = (Math.round(Math.random()) === 1) ? 200 : 404;
    console.log(status)
    if (status === 200)
        return res({ status })
    else
        return rej({ status })
  })
}

let promise =
httpRequest()
    .then(res => Promise.resolve('success'))
    .catch(e => {
        if (e.status === 404)
            return Promise.resolve('success')
        else
            return Promise.reject('failed')
    })

promise
.then(res => {
    console.log(res)
})
.catch(e => {
    console.log('this should not happen')
})

Respuesta #2

Si necesitas propagar tu flujo de éxito cuando lo "arregles", puedo pensar en dos enfoques aquí,

  1. Puedes encapsular tu lógica de propagación adicional en una función y luego llamarla en el escenario de error.
  2. Envuelve tu promise en otra promesa y llama a resolve(yourValue) en el error 404. Pero entonces esto significará que tendrás que cambiar tus lógicas encadenadas posteriores en el objeto promise, pero por el contrario esto te dará más flexibilidad.

Espero que ayude ;)

EDITAR

Después de ver tu código, todavía siento que es alcanzable con lo que he mencionado antes. Puedes hacer algo en la línea de -

refreshAsync = async () => {
   return new Promise((resolve,reject)=>{
       await this.$http.get(url).then(r => {
           this.data = r.data;
        }, error => {
            if (error.status == 404) {
                 resolve(); //populate this with your desired value
           } else {
                 reject();
           }
   })
}

Artículos relacionados