mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-24 14:41:20 -08:00
fix: silence unhandled play() rejections from internal callers
`art.play()` is an async wrapper around the native `video.play()` promise, which rejects when a pending play request is interrupted (`pause()`, `load()`, a new `src`, or the element being removed) and when autoplay is blocked. Every internal caller fires it from an event handler and cannot await it, so the rejection escapes as a global `unhandledrejection`. Error trackers report it as an uncaught crash even though the player recovers on its own — for example destroying the player right after mount, which is routine when the video sits in a modal the user can close quickly. Add a `silencePromise` util (the same approach video.js uses) and apply it to the non-awaited internal call sites: mask, play control, mini player, loop restart, autoPlayback jump, hotkey and click toggles. `switchMix` is fixed too, for a second symptom: `await art.play()` inside the async `video:canplay` handler both leaked the rejection and left the `switchUrl` promise pending forever, since the throw never reached the enclosing executor's `reject`. It now settles. The public API is unchanged: `art.play()` and `art.toggle()` still return the original promise, so applications that call them keep their own rejection to handle. Only the internal, non-awaited copy is silenced.
This commit is contained in:
1 parent
0b9c31a8cf
commit
0f47e11d63
10 files changed
+44
-18
No files matched your search
@@ -14,3 +14,28 @@ export function errorHandle(condition, msg) {
|
||||
}
|
||||
return condition
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a no-op catch to a promise that is intentionally not awaited.
|
||||
*
|
||||
* `art.play()` resolves the native `video.play()` promise, which rejects when the
|
||||
* request is interrupted (a `pause()`, a `load()`, a new `src`, or the element
|
||||
* being removed while the request is still pending) or when autoplay is blocked.
|
||||
* Internal call sites fire it from event handlers and cannot await it, so the
|
||||
* rejection escapes as a global `unhandledrejection` and error trackers report it
|
||||
* as a crash even though the player recovers on its own.
|
||||
*
|
||||
* Nothing is hidden from users of the public API: `art.play()` and `art.toggle()`
|
||||
* still return the original promise, so an application that calls them keeps its
|
||||
* own rejection to handle. Only the internal, non-awaited copy is silenced.
|
||||
*
|
||||
* Returns a promise that always fulfills, so an internal caller may await it
|
||||
* without inheriting the rejection. A non-thenable value is returned untouched
|
||||
* (`art.toggle()` yields `art.pause()`, which is synchronous).
|
||||
*/
|
||||
export function silencePromise(value) {
|
||||
if (value && typeof value.catch === 'function') {
|
||||
return value.catch(() => {})
|
||||
}
|
||||
return value
|
||||
}
|
||||
Reference in new issue
Block a user