Workaround for a disconnected worker on iOS
This commit is contained in:
parent
49e593d291
commit
4024cd1585
@ -4,6 +4,7 @@ import { WorkerMessageEvent, ThenArg, OriginRequest } from './types';
|
||||
|
||||
import { DEBUG } from '../../../config';
|
||||
import generateIdFor from '../../../util/generateIdFor';
|
||||
import { pause } from '../../../util/schedulers';
|
||||
|
||||
type RequestStates = {
|
||||
messageId: string;
|
||||
@ -12,6 +13,9 @@ type RequestStates = {
|
||||
callback?: AnyToVoidFunction;
|
||||
};
|
||||
|
||||
const HEALTH_CHECK_TIMEOUT = 1000; // 1 sec
|
||||
const HEALTH_CHECK_MIN_DELAY = 5 * 1000; // 5 sec
|
||||
|
||||
let worker: Worker;
|
||||
const requestStates = new Map<string, RequestStates>();
|
||||
const requestStatesByCallback = new Map<AnyToVoidFunction, RequestStates>();
|
||||
@ -27,6 +31,10 @@ export function initApi(onUpdate: OnApiUpdate, initialArgs: ApiInitialArgs) {
|
||||
|
||||
worker = new Worker(new URL('./worker.ts', import.meta.url));
|
||||
subscribeToWorker(onUpdate);
|
||||
|
||||
if (initialArgs.platform === 'iOS') {
|
||||
setupIosHealthCheck();
|
||||
}
|
||||
}
|
||||
|
||||
return makeRequest({
|
||||
@ -104,7 +112,7 @@ function makeRequest(message: OriginRequest) {
|
||||
Object.assign(requestState, { resolve, reject });
|
||||
});
|
||||
|
||||
if (typeof payload.args[1] === 'function') {
|
||||
if (('args' in payload) && typeof payload.args[1] === 'function') {
|
||||
const callback = payload.args.pop() as AnyToVoidFunction;
|
||||
requestState.callback = callback;
|
||||
requestStatesByCallback.set(callback, requestState);
|
||||
@ -125,3 +133,24 @@ function makeRequest(message: OriginRequest) {
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
const startedAt = Date.now();
|
||||
|
||||
// Workaround for iOS sometimes stops interacting with worker
|
||||
function setupIosHealthCheck() {
|
||||
window.addEventListener('focus', async () => {
|
||||
try {
|
||||
await Promise.race([
|
||||
makeRequest({ type: 'ping' }),
|
||||
pause(HEALTH_CHECK_TIMEOUT).then(() => Promise.reject(new Error('HEALTH_CHECK_TIMEOUT'))),
|
||||
]);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
|
||||
if (Date.now() - startedAt >= HEALTH_CHECK_MIN_DELAY) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -33,6 +33,9 @@ export type OriginRequest = {
|
||||
messageId?: string;
|
||||
name: keyof Methods;
|
||||
args: MethodArgs<keyof Methods>;
|
||||
} | {
|
||||
type: 'ping';
|
||||
messageId?: string;
|
||||
};
|
||||
|
||||
export type OriginMessageData = OriginRequest | {
|
||||
|
||||
@ -81,6 +81,14 @@ onmessage = async (message: OriginMessageEvent) => {
|
||||
cancelApiProgress(callback);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'ping': {
|
||||
sendToOrigin({
|
||||
type: 'methodResponse',
|
||||
messageId: data.messageId!,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user