Some uni-app platforms ignore the `timeout` option, leaving the returned
promise pending forever and hanging the calling page with no error path.
Drive the deadline locally: keep a single-shot `finish` guard so success,
failure and timeout can only settle once, and on timeout call `task.abort()`
before rejecting so the in-flight request is released instead of leaking.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>