Reputation: 16948
I am currently struggling to get to grips with the structure for the following implementation:
// Method from API Class (layer for communicating with the API)
call() {
// Return axios request BUT handle specific API errors e.g. '401 Unauthorized'
// and prevent subsequent calls to `then` and `catch`
}
// Method from Form Class (used for all forms)
submit() {
// Call the `call` method on the API class and process
// the response.
// IF any validation errors are returned then
// process these and prevent subsequent calls to `then`
// and `catch`
}
// Method on the component itself (unique for each form)
onSubmit() {
// Call the `submit` method on the Form class
// Process the response
// Handle any errors that are not handled by the parent
// methods
}
I have implemented this like so:
// Method from API Class (layer for communicating with the API)
call() {
// The purpose of this is to execute the API request and return
// the promise to the caller. However, we need to catch specific
// API errors such as '401 Unauthorized' and prevent any subsequent
// `then` and `catch` calls from the caller
return new Promise((resolve, reject) => {
this.axios.request(request)
.then(response => {
resolve(response); // Do I actually need to do this?
})
.catch(error => {
// Here we need to handle unauthorized errors and prevent any more execution...
reject(error);
});
});
}
// Method from Form Class (used for all forms)
submit() {
// The purpose of this is to call the API, and then, if it
// returns data, or validation errors, process these.
return new Promise((resolve, reject) => {
api.call()
.then(response => {
// Process form on success
this.onSuccess(response.data);
resolve(response.data);
})
.catch(error => {
// Process any validation errors AND prevent
// any further calls to `then` and `catch` from
// the caller (the form component)
this.onFail(error.response.data.error.meta);
reject(error);
})
.then(() => this.processing = false); // This MUST run
});
}
// Method on the component itself (unique for each form)
onSubmit() {
this.form.submit()
.then(response => {
// This should only run if no errors were caught in
// either of the parent calls
// Then, do some cool stuff...
});
}
My comments should explain what I am trying to achieve, but just to be clear:
then
and catch
from running from the calling class/component?new Promise
each time I return one?axios.request
already returns a Promise
but I don't know how to access the resolve
and reject
methods without wrapping it with a new Promise
. If this is wrong, please feel free to correct...Upvotes: 3
Views: 86
Reputation: 1074038
First: There's no need for new Promise
when you already have a promise to work with. So as a first step, let's fix (say) call
:
call() {
return this.axios.request(request)
.then(response => {
// ...
})
.catch(error => {
// ...
});
}
How do I catch certain errors, and then, prevent any further calls to
then
andcatch
from running from the calling class/component?
You don't. If you're returning a promise, it must settle (resolve or reject). Either involves subsequent handlers running. A promise is exactly that: A promise that you'll either provide a value (resolution) or an error (rejection).
The key concept you may be missing (lots of people do!) is that then
and catch
return new promises, which are resolved/rejected based on what their handlers do.
You can use a catch
handler to:
...but you can't suppress calls to subsequent callbacks.
You can use a then
handler to:
So for instance, if you have an error condition that you can correct (which is relatively rare, but happens), you can do this
.catch(error => {
if (/*...the error can be corrected...*/) {
return valueFromCorrectingTheProblem;
}
throw error; // Couldn't correct it
})
If you return a value (or a promise that resolves), the promise returned by catch
resolves with that value. If you throw (or return a promise that rejects), the promise returned by catch
rejects.
Is it actually necessary to create a new Promise each time I return one?
No, see above. (And good question.)
I know that
axios.request
already returns a Promise but I don't know how to access theresolve
andreject
methods without wrapping it with a new Promise.
You don't; you use then
and catch
. They return a new promise that will be resolved/rejected according to what happens in the handler.
Upvotes: 3