The beginning of the story
Recently, I encountered a problem in the project, and the business logic will not be introduced here. During the investigation, I found a code like this in the project:
fetch(url)
.then((res) = > res.text())
.then((text) = > {
const data = JSON.parse(text)
})
Copy the code
There is no catch operation on the last THEN, we suspect there is a problem here, because text may not parse to valid JSON, but in fact there is a global error catch in our project:
window.addEventListener('unhandledrejection'.(e) = > {
sendLog(e)
})
Copy the code
This is strange, huarong meet Guan Yu? Parse failed to catch json. parse, but the unhandledrejection event failed to catch json. parse We then tried the following code:
window.addEventListener('unhandledrejection'.event= > {
console.log('unhandledrejection:', event);
})
Promise.resolve("{")
.then((data) = > {
JSON.parse(data)
})
Copy the code
The following error message appears in the console:
Uncaught (in promise) SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
...
Copy the code
Parse failed to parse json. parse successfully. Indeed, it was not captured by unhandledrejection. Let’s just throw an error and see if the event works:
Promise.resolve()
.then(() = > {
throw 123
})
Copy the code
The following message appears on the console:
unhandledrejection: 123
Copy the code
Parse does not catch json.parse errors. Can’t catch syntax errors? If we can’t catch syntax errors, we can’t catch syntax errors in JSON:
Promise.resolve("{")
.then((data) = > {
eval(data)
})
Copy the code
Let’s look at the console output:
unhandledrejection: SyntaxError: Unexpected end of input
Copy the code
Parse (jSON.parse) was caught with a syntax error. Json.parse (jSON.parse) was caught with a syntax error. We tried the following again:
Promise.resolve("{")
.then((data) = > {
try {
JSON.parse(data)
} catch (e) {
throw e
}
})
Copy the code
The above attempt will result in an error via a try… catch… Catch, rethrow, and console output:
Uncaught (in promise) SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
Copy the code
The error message is still not caught. Let’s wrap up the error:
Promise.resolve("{")
.then((data) = > {
try {
JSON.parse(data)
} catch (e) {
const wraper = new SyntaxError(e.messgae)
wraper.stack = e.stack
throw wraper
}
})
Copy the code
Create an instance of SyntaxError wraper and place a try… catch… The captured error message is placed on wraper, and the console output is as follows:
unhandledrejection: SyntaxError: Unexpected end of input
Copy the code
The error does not appear in Firefox or Safari. The error does not appear in Firefox or Safari.
Interesting thing
In the comments on StackOverflow, a developer named Kaiido said it might be a Chrome bug and suggested I go to the Chromium Bug Report site to report it, but I found a similar report. The reporter says that he found that neither window.onerror nor unhandledrejection could catch a json. parse error:
window.onerror = async(... args) => {console.log("onerror")}window.addEventListener('unhandledrejection'.async function (event) {
console.log("unhandledrejection")})var elem = document.getElementById('button');
elem.addEventListener('click'.() = > { JSON.parse(undefined); })
Copy the code
Parse is not included in the Promise, so window.onerror can be caught. The reporter’s question is not appropriate. The maintainer opens the same version of chrome as the reporter (Chrome 88) and dark mode, opens a blank page of Chrome, pastes the code above into the console for execution, and displays the following error:
Uncaught TypeError: Cannot read property 'addEventListener' of null
at <anonymous>:11:6
Copy the code
Then the maintainer asked the reporter to point out the problem. We could all see that the error was caused by the lack of button element on the page, which had nothing to do with the error said by the reporter. Therefore, I suspected that the maintainer came to make fun of it. This morning, the speaker used the question I raised on StackOverflow as an example to explain the problem to the maintainer. So far, the maintainer has not replied, you can keep watching
The last
Parse (jSON.parse), then (catch), jSON.parse (jSON.parse), then (catch), json.parse (json.parse) catch…
This is also a thorny problem for the front-end error monitoring platform, and we hope to see a better solution in the future.
Cover image: Silly Mermaid by Iron Pillar stay and stay
Read more interesting articles on our official account