#javascript #typescript #service-worker #indexeddb
Вопрос:
Я создаю сотрудника службы, у которого есть несколько функций, использующих IndexDB. В этих функциях я получаю эти ошибки машинописи:
Property 'errorCode' does not exist on type 'EventTarget'
при использовании db.onsuccess
amp; db.onerror
вот мой код работника службы:
/// <reference no-default-lib="true"/>
/// <reference lib="ES2020" />
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
/// <reference lib="webworker" />
export type {};
declare const self: ServiceWorkerGlobalScope;
interface AccessCredentials {
accessToken: string;
refreshToken: string;
}
async function getAccessCredentials(): Promise<AccessCredentials> {
const databaseName = 'BATAccessTokens';
const databaseStore = 'BATAccessTokens';
return new Promise((resolve, reject) => {
const dbrequest = indexedDB.open(databaseName, 1);
dbrequest.onupgradeneeded = (event) => {
const database = dbrequest.resu<
database.createObjectStore(databaseStore, { autoIncrement: true });
database.onerror = () =>
reject(`ERROR: ${event.target.errorCode}`);
};
dbrequest.onerror = (event) =>
reject(`ERROR: ${event.target.errorCode}`);
dbrequest.onsuccess = (event) => {
const database = dbrequest.resu<
const transaction = database.transaction(databaseStore, 'readwrite');
const store = transaction.objectStore(databaseStore);
const request = store.get(1);
request.onsuccess = () => {
if (request.result) resolve(request.result);
resolve(null);
};
transaction.oncomplete = () => database.close();
database.onerror = () => resolve(null);
};
});
}
async function putAccessCredentials(credentials: AccessCredentials) {
const databaseName = 'BATAccessTokens';
const databaseStore = 'BATAccessTokens';
return new Promise((resolve, reject) => {
const dbrequest = indexedDB.open(databaseName, 1);
dbrequest.onupgradeneeded = () => {
const database = dbrequest.resu<
database.createObjectStore(databaseStore, { autoIncrement: true });
database.onerror = (event) =>
reject(`ERROR: ${event.target.errorCode}`);
};
dbrequest.onerror = (event) =>
reject(`ERROR: ${event.target.errorCode}`);
dbrequest.onsuccess = (event) => {
const database = dbrequest.resu<
const transaction = database.transaction(databaseStore, 'readwrite');
const store = transaction.objectStore(databaseStore);
const request = store.put(credentials, 1);
request.onsuccess = () => resolve(credentials);
transaction.oncomplete = () => database.close();
database.onerror = () =>
reject(`ERROR: ${event.target.errorCode}`);
};
});
}
async function putRBDSCode(RBDSCode) {
const databaseName = 'BATRBDSCode';
const databaseStore = 'BATRBDSCode';
return new Promise((resolve, reject) => {
const dbrequest = indexedDB.open(databaseName, 1);
dbrequest.onupgradeneeded = () => {
const database = dbrequest.resu<
database.createObjectStore(databaseStore, { autoIncrement: true });
database.onerror = (event) =>
reject(`ERROR: ${event.target.errorCode}`);
};
dbrequest.onerror = (event) =>
reject(`ERROR: ${event.target.errorCode}`);
dbrequest.onsuccess = (event) => {
const database = dbrequest.resu<
const transaction = database.transaction(databaseStore, 'readwrite');
const store = transaction.objectStore(databaseStore);
const request = store.put(RBDSCode, 1);
request.onsuccess = () => resolve(RBDSCode);
transaction.oncomplete = () => database.close();
database.onerror = () =>
reject(`ERROR: ${event.target.errorCode}`);
};
});
}
async function getClientList(): Promise<readonly WindowClient[]> {
const clientList = await self.clients.claim().then(() =>
self.clients.matchAll({
type: 'window'
})
);
return clientList;
}
self.addEventListener('install', (event) => {
console.log('Service Worker installed');
});
self.addEventListener('activate', (event) => {
console.log('Service Worker activated');
});
self.addEventListener('fetch', (event) => {
if (event.request.method === 'GET' amp;amp; event.request.mode === 'navigate') {
let request = event.request;
// console.log({request});
event.waitUntil(getClientList());
event.respondWith((async () => {
const clientList = await getClientList();
const client = clientList.find((item) => item.visibilityState === 'visible');
const url = client amp;amp; new URL(client.url);
const rbdsCode = url amp;amp; url.searchParams.get('RBDSCode');
const credentials = await getAccessCredentials();
const dppRequest = false;
const rbdsRequest = !!rbdsCode amp;amp; !dppRequest;
if (rbdsRequest amp;amp; !credentials) {
// console.log(client);
// client.navigate('/forms/login.html').then(() => client.focus())
request = new Request(`http://localhost:3000/forms/login.html`);
}
if (request amp;amp; credentials) {
// do something
}
if (dppRequest) {
// handle dpp request
}
if (credentials) request = new Request(request, {
headers: {
...request.headers,
Authorization: `Bearer ${credentials.accessToken}`
}
});
const eventResponse = await fetch(request).then((response) => {
let accessToken, refreshToken;
for (const header of response.headers.entries()) {
if (header[0] === 'accesstoken') accessToken = header[1];
if (header[0] === 'refreshtoken') refreshToken = header[1];
}
accessToken amp;amp; refreshToken amp;amp; putAccessCredentials({ accessToken, refreshToken });
return response;
});
return eventResponse;
})());
}
});
Комментарии:
1. Имеет ли значение изменение
errorCode
, чтобыerror
что-то изменить? Я спрашиваю, потому что пример, показанный в разделе IDBRequest.onerror , использует имя свойстваerror
для получения дополнительной информации — и предполагаетerror.target
, что оно относится к объекту (запроса), для которого.onerror
был установлен.2. нет, потому что аргумент функции здесь набран в событие, однако я думаю, что нашел обходной путь, используя
dbrequest.error.code
3. будьте осторожны с файлом объявления машинописного текста, который вы используете, многие библиотеки машинописного текста содержат неправильные объявления типов для IndexedDB
Ответ №1:
Распаковка ошибки, которую вы видите, немного:
Property 'errorCode' does not exist on type 'EventTarget'
Это имеет смысл, поскольку универсальный EventTarget
(например, элемент DOM) не имеет errorCode
свойства. Но Typescript здесь вам не поможет, так как он, по-видимому, не знает, какие конкретные типы интерфейсов используются для индексированных объектов БД, когда вы пишете event.target.result
.
В этом случае target
одно из этих событий является экземпляром IDBRequest… у которого также нет errorCode
собственности. Так что вы все равно получили бы аналогичную ошибку.
Как вы обнаружили, у IDBRequest
интерфейса действительно есть error
свойство, которое является исключением DOMException. В свою очередь, DOMException
интерфейс обладает code
свойством.
Тем не менее… code
свойство устарело — новые типы исключений DOMException не определяют новые коды, поэтому значение code
всегда будет равно 0. Вместо этого name
следует использовать исключение DOMException, если вам нужно устранить неоднозначность типов ошибок.