I'm working on an Ember app which uses Ember Data. We mainly use Rails and Postgres for the backend, but a smaller portion of our data is stored in a WordPress backend. WordPress is running on wp.example.com
.
Ember Data is setup to work with both the Rails and WordPress backends, so I can do things like this:
// Get WordPress category by slug
this.store.query('wordpress/category', { slug }).then((models) => {
// Leave page if no category was found
if (typeof models.get('firstObject') == 'undefined') this.transitionTo('backupRoute');
return models.get('firstObject');
});
Now I'd like to know how i can catch the error if the wp
subdomain is offline.
When I change the WordPress backend URL (I'm not sure if that's the best way to simulate a failure), I get (failed)net::ERR_NAME_NOT_RESOLVED
in Chrome DevTools after a few seconds and Ember showing error 500. Instead, I'd like to catch the network error and do something useful, in this case, a redirect.
Is there a way to catch those errors? Adding a simple catch()
breaks the page completely. It remains white for about two minutes while there's a pending request, then it shows 502 Bad Gateway. I also get this in the logs:
my_service_1 | (node:1) UnhandledPromiseRejectionWarning: [object Object]
my_service_1 | (node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 13)
This question was featured on today's episode of May I Ask a Question.
These code examples are from an Octane-style app and have Octane syntax, but the features are available in older Ember versions as well.
Some built-in Ember features will help you out here: Loading and Error Substates and the error event.
First, you need to throw the error. Then you need to add an error action and say what should happen when an error occurs. When your request errors, the error event fires automatically, and you can put your transition code there. The error event handling is a feature of Ember routes.
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
export default class ArticlesOverviewRoute extends Route {
@service store;
model(params) {
return this.store.query('wordpress/category', { slug }).then((models) => {
if (typeof models.get('firstObject') == 'undefined') {
throw new Error("Sorry, there was a problem")
};
});
}
@action
error(error, transition) {
this.transitionTo('backupRoute')
}
};
Alternatively, if your goal was to show an error page, you can do something simpler. Create an error template with this command: ember g template error
. This will create a template file, app/templates/error.hbs
. Put some text in the template, like "oops!", so you can see it once it's working.
You still need to throw the error so Ember can notice it, but you don't need the error action anymore. Ember will do the routing to the error template automatically.
export default class ArticlesOverviewRoute extends Route {
@service store;
model(params) {
return this.store.query('wordpress/category', { slug }).then((models) => {
if (typeof models.get('firstObject') == 'undefined') {
throw new Error("Sorry, there was a problem")
};
});
}
};
The error template can live at lots of different routes. The Guides have all the details, but generally speaking, you can put them inside your route folders, like some-route/error.hbs
or you can put them in the root of the app, like we did with ember g template error