#javascript
Вопрос:
Этот код должен выполнить следующее: Выполните поиск по всем ссылкам на текущей странице и проверьте наличие нескольких ошибок. Проверка должна быть проведена до отображения результатов на странице. Поэтому я хочу заполнить массив ошибками и вернуть его после завершения всех проверок.
interface LinkObject {
element: HTMLAnchorElement;
url: URL;
checkTrigger?: HTMLButtonElement;
}
interface ErrorObject {
element: HTMLElement;
errors: string[];
warnings: string[];
}
export default class LinkCheckTool {
protected linksObjects: LinkObject[] = [];
protected errors: ErrorObject[] = [];
constructor() {
document.querySelectorAll('a').forEach((linkElement) => {
const button: HTMLButtonElement = document.createElement('button');
button.classList.add('tb-o-linkobject__btn');
const url: URL = new URL(linkElement.href);
if (url) {
linkElement.appendChild(button);
this.linksObjects.push({
element: linkElement,
url: url,
checkTrigger: button
})
}
})
const errors = this.fetchErrors();
console.log(errors); // results in an empty array, so need to use async / await here
}
protected fetchErrors() {
const errors = [];
this.linksObjects.forEach((linkObject) => {
if (linkObject.url.protocol !== 'javascript:') {
fetch(linkObject.url.href)
.then((response) => (response))
.then((response) => {
if (!response.ok) {
// push to errors here
}
})
.catch((error) => {
// push to errors here
})
}
})
}
}
В этом случае вывод ошибок консоли, конечно, возвращает пустой массив. Как я могу использовать async / await и вернуть обещание здесь?
Комментарии:
1. Кроме того, после преобразования ошибок выборки в асинхронные конструкторы не могут быть асинхронными, поэтому вам также нужно будет сделать ->
this.fetchErrors().then(....
2. @MrMythical карта будет работать, но
.forEach(async
это не поможет.
Ответ №1:
Функция fetchErrors
здесь не асинхронна, потому что она не возвращается Promise
. И поскольку вы пытаетесь вызвать функцию в constructor
async/await
синтаксисе, она на самом деле не будет работать в этом контексте.
Вместо этого вам нужно использовать Promise
обратный вызов здесь. Вы можете применить этот Promise.allSettled
метод. Это поможет вам подождать, пока ваши запросы не будут решены, а затем вы сможете обрабатывать ответы один за другим.
constructor() {
// ...
const errors = [];
this.fetchErrors().then(results => {
results.forEach(result => {
if (result.status === "rejected") {
errors.push(result.value)
}
})
console.log(errors); // will print you list of errors
});
}
protected fetchErrors() {
const requests = this.linksObjects
.filter(linkObject => linkObject.url.protocol !== 'javascript:')
.map((linkObject) => fetch(linkObject.url.href))
return Promise.allSettled(requests);
}
Комментарии:
1. Отлично, спасибо. Ты сделал мой день лучше…