Similar a mi última pregunta pero lo suficientemente diferente como para estar perdido. Tengo la siguiente función en AngularJs que necesito recrear en VueJs. Tengo dos formas similares en las que he intentado escribir esto en VueJs, pero están causando muchas excepciones en el sitio en ambos sentidos.
AngularJs
var foo = function(obj, config) { if (config.skip) { return $q.reject("Skipping"); } var deferred = $q.defer(); obj.promise = deferred.promise; if (obj.hasValue()) { deferred.resolve(obj); } else { "/api/callToApi".$promise.then(function(res) { if (res) { deferred.resolve(res); else { deferred.reject(res); } }); } return deferred.promise; }
VueJs: toma 1. Estoy bastante seguro de que a este le falta el encadenamiento de promesa real, no estoy seguro de cómo configurarlo correctamente.
var foo = function(obj, config) { let returnEarly = false; let promise = new Promise((resolve, reject) => { returnEarly = true; reject("Skipping"): } if (returnEarly) { return promise; } obj.promise = promise; return new Promise((resolve, reject) => { if (obj.hasValue()) { resolve(obj); } else { axios.get("/api/callToApi").then(function(res) { if (res) { resolve(res); } else { reject(res); } } } } }
Errores de consola con la toma 1
Uncaught (in promise) Error: Request failed with status code 404 at XMLHttpRequest.__capture__.onreadystatechange
VueJs - toma 2. Pensé que de esta manera devolvería el encadenamiento correcto, pero aparece un error Timeout - Async callback was not invoked within the 5000ms timeout
de 5000 ms al ejecutar pruebas de broma.
var foo = function(obj, config) { let returnEarly = false; let promise = new Promise((resolve, reject) => { returnEarly = true; reject("Skipping"): } if (returnEarly) { return promise; } obj.promise = promise; return promise.then(() => { return new Promise((resolve, reject) => { if (obj.hasValue()) { resolve(obj); } else { axios.get("/api/callToApi").then(function(res) { if (res) { resolve(res); } else { reject(res); } } } } } }
Esto es JavaScript simple, no específico de Vue.
Por lo general, no es necesario asignar una promesa a obj.promise
porque se devuelve desde la función.
El uso excesivo de la new Promise
se conoce como constructor de promesas antipatrón. Si ya hay una promesa (Axios devuelve una), no es necesario crear una nueva, esto da como resultado un código redundante y propenso a errores (esta puede ser la razón por la Async callback was not invoked...
error). En caso de que sea necesario crear una nueva promesa, existen métodos de Promise
de acceso directo.
Debería ser algo como:
function(obj, config) { if (config.skip) { return Promise.reject("Skipping"); } if (obj.hasValue()) { return Promise.resolve(obj); } else { return axios("/api/callToApi").then(function(res) { if (res) return res; else throw res; } }); } }
Es una mala práctica en general cometer errores que no sean el objeto Error
.
También tenga en cuenta que el objeto de respuesta de Axios siempre es verdadero, posiblemente deba ser res.data
.
Será más conciso cuando se escriba como async... async..await
.