Similar to my last question but different enough that I am at a loss. I have the following function in AngularJs that I need to recreate in VueJs. I have two similar ways I've tried to write this in VueJs, but they are causing lots of site exceptions both ways.
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 - take 1. I'm pretty sure this one is missing the actual promise chaining, not sure how to correctly set that.
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);
}
}
}
}
}
Console errors with take 1
Uncaught (in promise) Error: Request failed with status code 404
at XMLHttpRequest.__capture__.onreadystatechange
VueJs - take 2. I thought this way would return the correct chaining, but I get an error Timeout - Async callback was not invoked within the 5000ms timeout
when running jest tests.
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);
}
}
}
}
}
}
CodePudding user response:
This is plain JavaScript, not specific to Vue.
It's generally unnecessary to assign a promise to obj.promise
because it's returned from the function.
Excessive use of new Promise
is known as promise constructor antipattern. If there's already a promise (Axios returns one), there's no need to create a new one, this results in redundant and error-prone code (this can be the reason for Async callback was not invoked...
error). In case a new promise needs to be created, there are shortcut Promise
methods.
Should be something like:
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;
}
});
}
}
It's a bad practice in general to make errors anything but Error
object.
Also notice that Axios response object is always truthy, possibly needs to be res.data
.
Will be more concise when written as async..await
.