How to handle client-side JavaScript errors with Nuxt.JS - javascript

I'm trying to show an error page when an error occurs on the client side Javascript of Vue components.
In dev mode, I get a customer error page I've created in the layouts/error.vue page whenever the client runs into an error. But when I build and start the app no error page is displayed even though the error is logged in the console. This error page is only displayed for server errors.
I've tried creating a custom error handling component using the following code:
mounted() {
window.onerror = this.onError
},
methods: {
onError(msg, source, ln, cn, err) {
console.log('Error received')
this.show = true
this.error = { msg, source, ln, cn, err }
}
}
However, this function does not seem to handle the client sides error that occurs.
Does anyone know what the best way is to handle all unhandled clients side errors?

Related

How to trigger nextjs default 500 error page

I am unable to trigger the Next.js's 500 error page. Most resources talks about making a custom error page but the Next.js doc briefly mentions their default 500 error page. I would like to trigger this default page when the API responds with a 500 status.
Given an API response of 500 Next.js should display a 500 error page. So far it returns to the page where the request was made.
return res.status(500).end();
The only solution I found is to throw an unhandled error from getServerSideProps:
res.statusCode = 500;
throw new Error('Internal Server Error');
I saw that NextJs handle this as a 500 status code, but only on the production/staging environment. npm run dev will not work, and you will not be able to see the default 500 page.
I needed to throw a 500 status code to prevent Google from deindexing my page because the page content suffered significant changes, and the products from this page were not available anymore.
This is how I was able to trigger this, using npm run build and npm run start
(I put this random error trigger in my index page)
export const getServerSideProps: GetServerSideProps = async () => {
function getRandomInt(max: number): number {
return Math.floor(Math.random() * max);
}
if (getRandomInt(10) === 5) {
throw new Error('Internal Server Error');
}
return {
props: {
},
}
}
After defining the custom 500 page at pages/500.ts as mentioned in the official doc, I'm able to access this page at the url path /500.

FirebaseError when logging out of web app, exception thrown by user callback, document references must have an even number of segments

I've built a Javascript web app using Firestore and Firebase. When logging the user out, I am getting console errors. The errors reference the firebase-database.js and firebase-firestore.js scripts, though, so I can't really tell what is happening:
[2020-05-22T12:32:58.436Z] #firebase/database: FIREBASE WARNING:
Exception was thrown by user callback.
Hr#https://www.gstatic.com/firebasejs/7.6.1/firebase-firestore.js:1:48219
firebase-database.js:1:11297
FirebaseError: Invalid document reference. Document references must
have an even number of segments, but user has 1
firebase-firestore.js:1:48219
This is my log out function:
$('.logout').on('click', function(){
firebase.auth().signOut()
.catch(function(error){
console.log(error.code);
console.log(error.message);
});
});
Then I have a listener for firebase.auth().onAuthStateChanged which triggers this:
firestoredb.collection('user').doc(uid).update({
status: false,
last_changed: firebase.firestore.FieldValue.serverTimestamp()
})
.then(function(){
uid='';
$('#screenname').html('');
window.location='https://www.example.com/your-account.asp?task=logout&afterlogin=%2Fv2';
})
.catch(function(error){
console.log(error.code);
console.log(error.message);
});
What might be my strategy for tracking down this error since the console logs are not that helpful? The error does not really affect the performance of the app, since the user is logged out anyway (and redirected via Javascript), however it bothers me that there is an error.
EDIT: I am wondering if the cloud script that is running could be the problem. That might explain why I cannot identify the line number and why the error message is so vague. Here is my cloud script, can this be modified so that a missing UID value would be ignored? This is basically the script provided by Google for combining Firebase and Firestore to maintain session state of the user.
const functions=require('firebase-functions');
const admin=require('firebase-admin');
admin.initializeApp();
const firestore=admin.firestore();
exports.onUserStatusChanged=functions.database.ref('user/{uid}').onUpdate(
async (change, context) => {
const eventStatus=change.after.val();
const userStatusFirestoreRef=firestore.doc(`user/${context.params.uid}`);
const statusSnapshot=await change.after.ref.once('value');
const status=statusSnapshot.val();
if (status.last_changed>eventStatus.last_changed){
return null;
}
eventStatus.last_changed=new Date(eventStatus.last_changed);
return userStatusFirestoreRef.update(eventStatus);
}
);

videojs - How to catch custom http error codes during live stream?

I have a live stream (HLS) that I am playing using videojs 6.8. For some users, after the playback has started (about 4-5 .ts files have been loaded) the server throws me a 409 error.
How do I catch this specific error code so that I can programmatically stop the playback and show an error message?
Currently, videojs keeps trying to resume playback indefinitely. I have tried retryplaylist, blacklistplaylist but all the info I get is that the playlist has been blacklisted and is being retried, I do not see the HTTP code anywhere in my console.log(). player.on('error') doesn't throw any error. I have tried all three of the following but none of them gives me the http code:
player.on('error', function (e) {
// no log
console.log(e);
})
player.tech().on('retryplaylist', function (e, data) {
// logs that it is being retried, but no http code
console.log('retry');
console.log(e);
})
player.tech().on('usage', function (e, data) {
// logs the even 'retryplaylist` but does not give me a http code.
console.log('usage');
console.log(e)
})
I do not want to put my message in retryplaylist because that event will be thrown in case of a slow network too (I already tested this).
What do I have to do to catch the specific 409 error?
Look like:
var retries = 0;
player.tech().on('retryplaylist', function (e, data) {
retries++;
if (retries >= 3) {
// do something
}
})

how to catch error in firestore when no internet

I recently updated my app from firebase to firestore but stuck at offline persistance. I am using react-native-firebase to integrate firestore and disable its perisistance but still not getting any catch error when no internet.
This is my code to delete data but catch never gets error when no internet not is the promise resolved.
firebase.firestore().collection('d').doc(deviceid).delete().then(function () {
console.log("Device Deleted");
that.setState({
loading: false
});
Toast.show('Device Deleted Succesfully', {
duration: Toast.durations.SHORT,
position: Toast.positions.TOP,
shadow: true,
animation: true,
hideOnPress: true,
delay: 0,
});
}).catch(function (err) {
console.log(err);
that.setState({
loading: false
});
})
Firestore and Realtime Database SDKs don't throw errors when there is no network connectivity. They will silently retry the connection in hopes that the device will regain network connectivity soon. The reason for this is because most developers don't want their apps to appear broken just because the user went into a tunnel and back out, or switched between mobile towers in a way that forced a network reset.
In order to effectively make use of an online database, the device should be online most of the time, and this the situation that the SDK is optimizing for.
Make your own helper function for deletion that throws an error if there is no Internet connection. You can make the API cleaner by not calling .collection() but rather passing the full path d + deviceid to it.
function onlineOnlyDelete(path) {
if(!deviceApi.hasInternet()) throw 'No Internet, no delete'
return firebase.firestore().doc(path).delete()
}
replace firebase.firestore().collection('d').doc(deviceid) with onlineOnlyDelete(d+deviceid) and you should be good to go
Referencing this thread. I set up the following check:
.then(() => {
if (snapshot.empty && snapshot.metadata.fromCache) {
throw new Error('Failed to fetch ideas');
}
})
Then later on I caught the error and set the app state to include the error along with parameters specific to the batch like startIndex and stopIndex which will be important later. When rendering the documents, one case is reserved for the BatchError as I dubbed it, in which case the user is going to see a Refetch button which has a callback attached to it. Using the batch metadata, the callback is able to reinitialize the specific batch request.

vue-resource: catch "Uncaught (in promise)" when intercepting an ajax error

I'm using vue-resource to fetch data from the server. A user needs to have a JWT token to get the correct data. If the token is invalid or expired, a 401 status is returned. If the user tries to access a forbidden page, a 403 is returned.
I would like to catch those errors and handle them appropriately (globally). This means, that the calls should be completely handled by the interceptor (if 401, 403).
How can I prevent the browser message "Uncaught (in promise)" and create some global error handling? I don't want to have a local error handler on every call.
I have the following interceptor:
Vue.http.interceptors.push(function (request, next) {
request.headers.set('Authorization', Auth.getAuthHeader());
next(function (response) {
if (response.status === 401 || response.status === 403) {
console.log('You are not logged in or do not have the rights to access this site.');
}
});
});
And the following call in the Vue methods:
methods: {
user: function () {
this.$http.get('http://localhost:8080/auth/user').then(function (response) {
console.log(response);
});
}
}
This is a bit of a dilemma, isn't it. You don't want unhandled promise rejections to get swallowed, because it means your application might not function and you won't know why, and will never get a report of the error happening.
On the other hand, it's silly to use the exact same error handling mechanism for every single .catch() statement in your application, so implementing a global error handler is definitely the way to go.
The problem is that in most cases, you will have to re-throw the error from your global error handler, because otherwise your application will think the request went through ok and will proceed to process the data, which will not exist.
But this leads to the situation where the Uncaught (in promise) error shows up, because the browser will think you didn't handle the error, whereas in reality you did, in your global error handler.
To get around this, there is now the onunhandledrejection event, and you can use that to prevent the browser from logging these errors, but then you have to make sure you process them yourself.
So what we often do is have our own error classes, and when a response error is thrown, we convert the error to one of our error classes, depending on the HTTP status code.
We also append a property to this error, something like ignoreUnhandledRejection and set it to true. Then, you can use the global handler to filter out those errors and ignore them, because you know that you have already handled them globally:
/**
* Prevent logging already processed unhandled rejection in console
*/
window.addEventListener('unhandledrejection', event => {
if (event.reason && event.reason.ignoreUnhandledRejection) {
event.preventDefault();
}
});

Categories

Resources