forked from mystiq/hydrogen-web
Move timeout to fetch, as XHR has native timeout support
This commit is contained in:
parent
3a5e3a69f2
commit
e8e9740521
4 changed files with 83 additions and 84 deletions
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
// import {RecordRequester, ReplayRequester} from "./matrix/net/request/replay.js";
|
||||
import {fetchRequest} from "./matrix/net/request/fetch.js";
|
||||
import {createFetchRequest} from "./matrix/net/request/fetch.js";
|
||||
import {SessionContainer} from "./matrix/SessionContainer.js";
|
||||
import {StorageFactory} from "./matrix/storage/idb/StorageFactory.js";
|
||||
import {SessionInfoStorage} from "./matrix/sessioninfo/localstorage/SessionInfoStorage.js";
|
||||
|
@ -32,13 +32,13 @@ export default async function main(container) {
|
|||
// const request = replay.request;
|
||||
|
||||
// to record:
|
||||
// const recorder = new RecordRequester(fetchRequest);
|
||||
// const recorder = new RecordRequester(createFetchRequest(clock.createTimeout));
|
||||
// const request = recorder.request;
|
||||
// window.getBrawlFetchLog = () => recorder.log();
|
||||
// normal network:
|
||||
const request = fetchRequest;
|
||||
const sessionInfoStorage = new SessionInfoStorage("brawl_sessions_v1");
|
||||
const clock = new Clock();
|
||||
const request = createFetchRequest(clock.createTimeout);
|
||||
const sessionInfoStorage = new SessionInfoStorage("brawl_sessions_v1");
|
||||
const storageFactory = new StorageFactory();
|
||||
|
||||
const vm = new BrawlViewModel({
|
||||
|
|
|
@ -21,9 +21,9 @@ import {
|
|||
} from "../error.js";
|
||||
|
||||
class RequestWrapper {
|
||||
constructor(method, url, requestResult, responsePromise) {
|
||||
constructor(method, url, requestResult) {
|
||||
this._requestResult = requestResult;
|
||||
this._promise = responsePromise.then(response => {
|
||||
this._promise = requestResult.response().then(response => {
|
||||
// ok?
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response.body;
|
||||
|
@ -60,35 +60,6 @@ export class HomeServerApi {
|
|||
return `${this._homeserver}/_matrix/client/r0${csPath}`;
|
||||
}
|
||||
|
||||
_abortOnTimeout(timeoutAmount, requestResult, responsePromise) {
|
||||
const timeout = this._createTimeout(timeoutAmount);
|
||||
// abort request if timeout finishes first
|
||||
let timedOut = false;
|
||||
timeout.elapsed().then(
|
||||
() => {
|
||||
timedOut = true;
|
||||
requestResult.abort();
|
||||
},
|
||||
() => {} // ignore AbortError
|
||||
);
|
||||
// abort timeout if request finishes first
|
||||
return responsePromise.then(
|
||||
response => {
|
||||
timeout.abort();
|
||||
return response;
|
||||
},
|
||||
err => {
|
||||
timeout.abort();
|
||||
// map error to TimeoutError
|
||||
if (err instanceof AbortError && timedOut) {
|
||||
throw new ConnectionError(`Request timed out after ${timeoutAmount}ms`, true);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
_encodeQueryParams(queryParams) {
|
||||
return Object.entries(queryParams || {})
|
||||
.filter(([, value]) => value !== undefined)
|
||||
|
@ -118,19 +89,10 @@ export class HomeServerApi {
|
|||
method,
|
||||
headers,
|
||||
body: bodyString,
|
||||
timeout: options && options.timeout
|
||||
});
|
||||
|
||||
let responsePromise = requestResult.response();
|
||||
|
||||
if (options && options.timeout) {
|
||||
responsePromise = this._abortOnTimeout(
|
||||
options.timeout,
|
||||
requestResult,
|
||||
responsePromise
|
||||
);
|
||||
}
|
||||
|
||||
const wrapper = new RequestWrapper(method, url, requestResult, responsePromise);
|
||||
const wrapper = new RequestWrapper(method, url, requestResult);
|
||||
|
||||
if (this._reconnector) {
|
||||
wrapper.response().catch(err => {
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
AbortError,
|
||||
ConnectionError
|
||||
} from "../../error.js";
|
||||
import {abortOnTimeout} from "../timeout.js";
|
||||
|
||||
class RequestResult {
|
||||
constructor(promise, controller) {
|
||||
|
@ -31,9 +32,9 @@ class RequestResult {
|
|||
}
|
||||
};
|
||||
});
|
||||
this._promise = Promise.race([promise, abortPromise]);
|
||||
this.promise = Promise.race([promise, abortPromise]);
|
||||
} else {
|
||||
this._promise = promise;
|
||||
this.promise = promise;
|
||||
this._controller = controller;
|
||||
}
|
||||
}
|
||||
|
@ -43,11 +44,12 @@ class RequestResult {
|
|||
}
|
||||
|
||||
response() {
|
||||
return this._promise;
|
||||
return this.promise;
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchRequest(url, options) {
|
||||
export function createFetchRequest(createTimeout) {
|
||||
return function fetchRequest(url, options) {
|
||||
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
||||
if (controller) {
|
||||
options = Object.assign(options, {
|
||||
|
@ -85,5 +87,12 @@ export function fetchRequest(url, options) {
|
|||
}
|
||||
throw err;
|
||||
});
|
||||
return new RequestResult(promise, controller);
|
||||
const result = new RequestResult(promise, controller);
|
||||
|
||||
if (options.timeout) {
|
||||
result.promise = abortOnTimeout(createTimeout, options.timeout, result, result.promise);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
28
src/matrix/net/timeout.js
Normal file
28
src/matrix/net/timeout.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
export function abortOnTimeout(createTimeout, timeoutAmount, requestResult, responsePromise) {
|
||||
const timeout = createTimeout(timeoutAmount);
|
||||
// abort request if timeout finishes first
|
||||
let timedOut = false;
|
||||
timeout.elapsed().then(
|
||||
() => {
|
||||
timedOut = true;
|
||||
requestResult.abort();
|
||||
},
|
||||
() => {} // ignore AbortError when timeout is aborted
|
||||
);
|
||||
// abort timeout if request finishes first
|
||||
return responsePromise.then(
|
||||
response => {
|
||||
timeout.abort();
|
||||
return response;
|
||||
},
|
||||
err => {
|
||||
timeout.abort();
|
||||
// map error to TimeoutError
|
||||
if (err instanceof AbortError && timedOut) {
|
||||
throw new ConnectionError(`Request timed out after ${timeoutAmount}ms`, true);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue