2019-12-23 14:28:27 +01:00
|
|
|
import {
|
2020-04-04 17:34:46 +02:00
|
|
|
AbortError,
|
2020-04-19 19:05:12 +02:00
|
|
|
ConnectionError
|
2020-04-20 19:47:45 +02:00
|
|
|
} from "../../error.js";
|
2019-12-23 14:28:27 +01:00
|
|
|
|
|
|
|
class RequestResult {
|
|
|
|
constructor(promise, controller) {
|
|
|
|
if (!controller) {
|
|
|
|
const abortPromise = new Promise((_, reject) => {
|
|
|
|
this._controller = {
|
|
|
|
abort() {
|
|
|
|
const err = new Error("fetch request aborted");
|
|
|
|
err.name = "AbortError";
|
|
|
|
reject(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
this._promise = Promise.race([promise, abortPromise]);
|
|
|
|
} else {
|
|
|
|
this._promise = promise;
|
|
|
|
this._controller = controller;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abort() {
|
|
|
|
this._controller.abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
response() {
|
|
|
|
return this._promise;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-20 21:26:39 +02:00
|
|
|
export function fetchRequest(url, options) {
|
2019-12-23 14:28:27 +01:00
|
|
|
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
|
|
if (controller) {
|
|
|
|
options = Object.assign(options, {
|
|
|
|
signal: controller.signal
|
|
|
|
});
|
|
|
|
}
|
|
|
|
options = Object.assign(options, {
|
|
|
|
mode: "cors",
|
|
|
|
credentials: "omit",
|
|
|
|
referrer: "no-referrer",
|
|
|
|
cache: "no-cache",
|
|
|
|
});
|
2020-04-22 20:46:47 +02:00
|
|
|
if (options.headers) {
|
|
|
|
const headers = new Headers();
|
|
|
|
for(const [name, value] of options.headers.entries()) {
|
|
|
|
headers.append(name, value);
|
|
|
|
}
|
|
|
|
options.headers = headers;
|
|
|
|
}
|
2019-12-23 14:28:27 +01:00
|
|
|
const promise = fetch(url, options).then(async response => {
|
|
|
|
const {status} = response;
|
|
|
|
const body = await response.json();
|
|
|
|
return {status, body};
|
|
|
|
}, err => {
|
|
|
|
if (err.name === "AbortError") {
|
2020-04-04 17:34:46 +02:00
|
|
|
throw new AbortError();
|
2019-12-23 14:28:27 +01:00
|
|
|
} else if (err instanceof TypeError) {
|
|
|
|
// Network errors are reported as TypeErrors, see
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful
|
|
|
|
// this can either mean user is offline, server is offline, or a CORS error (server misconfiguration).
|
|
|
|
//
|
|
|
|
// One could check navigator.onLine to rule out the first
|
2020-04-18 19:16:16 +02:00
|
|
|
// but the 2 latter ones are indistinguishable from javascript.
|
2020-04-19 19:05:12 +02:00
|
|
|
throw new ConnectionError(`${options.method} ${url}: ${err.message}`);
|
2019-12-23 14:28:27 +01:00
|
|
|
}
|
|
|
|
throw err;
|
|
|
|
});
|
|
|
|
return new RequestResult(promise, controller);
|
|
|
|
}
|