fix(reminder): ExpoLocationMonitor.chainSync() 在 syncRegions() 意外抛错时有崩溃风险 - #348
Merged
LUPENGHAN merged 1 commit intoAug 21, 2026
Conversation
…ns()
syncRegions() has two unguarded awaits (getForegroundPermissionsAsync/
getBackgroundPermissionsAsync) that can reject for real on a native module
hiccup, not just resolve to a denied status. chainSync() chained with
.then(onFulfilled, onRejected), so a rejection sits unhandled until some
later chainSync() call chains onto it. handleAppState's resync is
fire-and-forget (void this.chainSync()) with no such follow-up guaranteed --
if the rejection lands there, Node/Hermes treats it as an unhandled
rejection and crashes the process outright. Reproduced with a mocked
permission call that rejects.
Switch to .then(onFulfilled).catch(() => {}), the same idiom already used by
AssistantContinuousConversationService.chainPlayback(): the .catch() is
attached in the same statement, so the rejection is neutralized immediately
instead of waiting on a future call that may never come.
Fixes 1024XEngineer#347.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
LUPENGHAN
marked this pull request as ready for review
August 21, 2026 07:50
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
yyy-router
approved these changes
Aug 21, 2026
Contributor
There was a problem hiding this comment.
审阅了固定提交范围 81438d1511307b560a67bab2cc96f7184fb5df71...c51024957481d7b60cfecad5bbcaa597a6101e6b 中的 ExpoLocationMonitor.chainSync() 及其回归测试。将 rejection handler 从 .then(onFulfilled, onRejected) 改为同一表达式中的 .then(...).catch(...),确实会立即覆盖 fire-and-forget 的 handleAppState 路径,同时保留后续同步继续排队的行为;新增测试也覆盖了失败后的恢复路径。未发现满足报告阈值的正确性、可靠性或兼容性问题。
验证:git diff --check 通过。尝试运行聚焦 Jest 测试,但当前工作区未安装依赖,jest-expo preset 缺失,因此未能执行测试。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
变更说明
ExpoLocationMonitor.chainSync()之前用.then(onFulfilled, onRejected)排队执行syncRegions(),syncRegions()内部两处getForegroundPermissionsAsync()/getBackgroundPermissionsAsync()调用没有包 try/catch,一旦原生定位模块真的抛出异常(不是返回 denied),这次失败要等到下一次chainSync()调用才会被接住。handleAppState里触发的那条重同步路径是发射后不管的(void this.chainSync()),如果失败恰好发生在那里、短时间内又没有下一次调用兜底,这个被拒绝的 promise 就会一直没人处理,被 JS 运行时判定成 unhandled rejection,直接把 App 进程崩溃退出。改成
.then(onFulfilled).catch(() => {})——跟同项目AssistantContinuousConversationService.chainPlayback()已经在用的写法一致,.catch()在同一条语句里同步接上,不会再有"没人接"的窗口期。Closes #347。
测试计划
npx jest --runInBand(前端全量,614/614 绿)npx tsc --noEmitnpx eslint(改动到的文件)handleAppState触发同步,验证进程不崩溃、后续同步能正常恢复;已验证过旧代码上这条测试会失败(复现了同一个 unhandled rejection)🤖 Generated with Claude Code