-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
errorHandler not working in Promises / async #7653
Comments
I like that idea, since |
This feature would be a great add! Here's another example of how it currently works: new Vue({
el: '#app',
methods: {
async asyncMethod() {
throw new Error('This does NOT get caught by Vue') // wish this were caught
},
regularMethod() {
throw new Error('This gets caught by Vue') // yay!
},
},
}) As a workaround, you can catch the error in a try / catch block. But I couldn't find a way to trigger an error on the Vue instance. Is this possible? methods: {
async asyncMethod() {
try {
throw new Error('This does NOT get caught by Vue')
} catch (err) {
// Can you trigger the Vue instance's 'errorCaptured' callback from here?
}
}
}, I thought maybe the convention of emitting an this.$emit('error', error) // no special treatment of 'error' event |
I think it is very comfortable for Vuex actions. I wish to be implemented asap. vuex/actions.js async POST_SOMETHING({commit}, params) {
await requireAuthAction()
const { data } = await axios.post(`/api/something`, params)
commit("POST_SOMETHING", data)
}, main.js Vue.config.errorHandler = (err) => {
alert(err.message)
} |
Until this issue is fixed I am using a hacky mixin to catch errors thrown in async methods and send them to errorHandler: import Vue from 'vue'
// This mixin fixes following issue:
// errorHandler does not work with async component methods
// https://github.com/vuejs/vue/issues/7653
export default {
beforeCreate() {
const methods = this.$options.methods || {}
Object.entries(methods).forEach(([key, method]) => {
if (method._asyncWrapped) return
const wrappedMethod = function (...args) {
const result = method.apply(this, args)
const resultIsPromise = result && typeof result.then == 'function'
if (!resultIsPromise) return result
return new Promise(async (resolve, reject) => {
try {
resolve(await result)
} catch (error) {
if (!error._handled) {
const errorHandler = Vue.config.errorHandler || console.error
errorHandler(error)
error._handled = true
}
reject(error)
}
})
}
wrappedMethod._asyncWrapped = true
methods[key] = wrappedMethod
})
},
} |
@Doeke Any way to get that working with the |
@ErikBjare you could loop through |
Hi, I expanded Doeke's mixin to simulate propagation to errorCaptured hooks, which may also be async. Not sure it works 100% to spec, but it may help someone temporarily until this issue is resolved: import Vue from 'vue'
// This mixin fixes following issue:
// errorHandler does not work with async component methods
// https://github.com/vuejs/vue/issues/7653
async function propagateErrorCaptured(component, error, vm) {
let continuePropagation = true
const ec = component.$options.errorCaptured
if (ec instanceof Array) {
for (let i = 0; i < ec.length; i++) {
continuePropagation = ec[i].apply(component, [error, vm])
if (typeof continuePropagation === "object" && typeof continuePropagation.then === "function") {
// wait for the promise
continuePropagation = await continuePropagation
}
if (!continuePropagation) break;
}
}
if (component.$parent && continuePropagation) {
return await propagateErrorCaptured(component.$parent, error, vm)
} else {
return continuePropagation
}
}
export default {
beforeCreate() {
const methods = this.$options.methods || {}
Object.entries(methods).forEach(([key, method]) => {
const wrappedMethod = function (...args) {
const result = method.apply(this, args)
const resultIsPromise = result && typeof result.then == 'function'
if (!resultIsPromise) return result
return new Promise(async (resolve, reject) => {
try {
resolve(await result)
} catch (error) {
const continuePropagation = await propagateErrorCaptured(this, error, this)
if (!continuePropagation) {
if (Vue.config.errorHandler) {
Vue.config.errorHandler(error, this)
} else {
reject(error)
}
}
}
})
}
methods[key] = wrappedMethod
})
},
} |
@Doeke Hi, your code is nice, but if it catch error by reject('......') ? |
Closed via #8395 (will be out 2.6) |
Is there a way for me to install vue@2.6 before it's released? I tried specifying https://github.com/vuejs/vue.git#2.6 in my dependencies, but then I get an error about vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options. I have vue-template-compiler in my devDependencies (^2.5.17) but for some reason it's not finding it, even though Vue 2.5.17 did. If not, I'll just wait until 2.6 is out, but this is something we just recently found we needed. Thanks. |
@daviesdoclc we just released 2.6.0-beta.1 |
@yyx990803 thanks. I just tried it but it's not solving my issue. It does solves the initial issue addressed at the beginning of this thread. However this still spits out "Uncaught (in promise) Error" in my case where I'm calling a plain javascript service for example (simplified below).
Suggestions on how to handle this pattern? (if I shouldn't be commenting on a closed issue let me know) |
@daviesdoclc |
@yyx990803 sorry, that was a bad example. Yes, putting return on that does work in that scenario. However, that isn't my real world scenario, I was just trying to simplify. Here's where I'm having trouble.
During created I am calling several services to get and set data elements. In this particular case it would be nice to not have to catch everything, but instead have it call the general error handler. This was the case I hoped it would work with. |
I found this blog entry https://blog.bugsnag.com/anatomy-of-a-javascript-error/ that describes this situation. The suggestion is to either use a catch statement for all promise chains OR use unhandledrejection (which is only supported on Chrome right now). Sorry to have confused this with The Vue issue mention in this ticket. |
…handlers (vuejs#8395) close vuejs#6953, close vuejs#7653
Unless I'm missing something, f2009@c6c6d79 doesn't seem to account for async watcher callbacks. JSFiddle |
I'm also facing some issues with async methods. My project uses Typescript through https://github.com/kaorun343/vue-property-decorator and even with Vue 2.6 when doing: |
This is working for me:
|
Version
2.5.13
Reproduction link
https://jsfiddle.net/zr7rz6xh/8/
Steps to reproduce
Vue.config.errorHandler = function (err, vm, info) {
alert("handler");
};
new Vue({
el: '#app',
mounted: function() {
return new Promise(function(resolve, reject) {
throw new Error('err');
});
}
})
What is expected?
errorHandler should be called
What is actually happening?
Uncaught (in promise) Error: err
Vue.config.errorHandler is not called if the error occurs inside a promise or await/async function.
I want to use the created hook with an await call, so it has to be async. But then the errorHandler is ignored.
The text was updated successfully, but these errors were encountered: