Как справиться с этим fetch () TypeError? - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь вывести на консоль (чтобы потом обработать эти крайние случаи) статус ответа моего запроса на выборку.Тем не менее, единственный вызов console.log, который работает, - это вызов функции 'breaches'.Я не получаю ошибок, когда учетная запись существует в базе данных HIBP, но я получаю сообщение «Ошибка запроса: TypeError: response.json не является функцией в json», когда учетная запись не находится в базе данных.Что я делаю неправильно?Я получил код обработки ошибок из статей Google Web Dev .

function createNode(element) {
    return document.createElement(element);
}

function append(parent, el) {
    return parent.appendChild(el);
}

function status(response) {
    if (response.status >= 200 && response.status < 300) {
        return Promise.resolve(response)
        console.log('all is good');
    } else if (response.status == 404) {
        return Promise.resolve(response.statusText)
        console.log('no breaches');
    } else if (response.status == 400) {
        return Promise.resolve(response.statusText)
        console.log('bad req');
    } else {
        return Promise.reject(new Error(response.statusText))
    }
}

function json(response) {
    return response.json()
}

var account = document.getElementById('account'),
    results = document.getElementById('results');
account.addEventListener("keyup", keyupEvent);

function keyupEvent() {
    event.preventDefault();
    if (event.key === "Enter") {
        fetch('https://haveibeenpwned.com/api/v2/breachedaccount/' + account.value, {
                timeout: 1500,
                userAgent: 'test'
            })
            .then(status)
            .then(json)
            .then(function(breaches) {
                console.log('Status Code: ' + breaches.status);
                let span = createNode('span');
                return breaches.forEach(function(check) {
                    span.innerHTML = `${check.Name}<br/>`;
                    append(results, span)
                })

            }).catch(function(error) {
                console.log('Request failed:', error);
            });
    }
}

1 Ответ

0 голосов
/ 11 октября 2018

Ваша функция status возвращает (обещает) статус текст для ответов, которые имеют значение 400 или 404.Ваша цепочка обещаний, потребляющая результат fetch, не справляется с такой возможностью;он предполагает, что получает объект ответа.

Вы, вероятно, хотите отклонить на 400 или 404, а не на разрешении, но если нет, вам нужно перейти в ваш обработчик then, ожидающий чтения JSON.

Ваш код, использующий нарушения, также перезаписывает тот же span и многократно добавляет его;он будет добавлен только один раз, с информацией о взломе last .И функция append не предоставляет никакой полезной абстракции, кроме простого вызова appendChild.

Если API действительно возвращает 404 для «без нарушений» (blech), то я бы избавился от createNode и append, измените status на это:

function status(response) {
    if (response.ok) {
        return response.json();
    } else if (response.status === 404) { // If the API *really* returns
        return [];                        // a 404 for "no breaches"
    } else {
        throw new Error(response.statusText);
    }
}

, а затем:

fetch('https://haveibeenpwned.com/api/v2/breachedaccount/' + account.value, {
        timeout: 1500,
        userAgent: 'test'
    })
    .then(status)
    .then(breaches => {
        // No `return` here, the chain isn't passed on and there
        // aren't any further resolution handlers
        breaches.forEach(check => {  // Or a for-of loop
            const span = document.createElement("span");
            span.innerHTML = `${check.Name}<br/>`;
            results.appendChild(span);
        });
    }).catch(error => {
        console.log('Request failed:', error);
    });

Отдельно: ваша функция status предполагает, что вы этого не делаетеосознайте, что thencatch) создают новые обещания .У вашей status функции нет причин создавать какие-либо обещания, если она будет использоваться только в качестве обработчика then.Он должен просто вернуть значение (обещание, созданное then будет разрешено с этим значением) или выдать ошибку (обещание, созданное then отклонит с этой ошибкой):

// This is equivalent to your current `status` function (assuming it's always
// used as a `then` callback)
function status(response) {
    if (response.ok) { // if (response.status >= 200 && response.status < 300) {
        // all okay
        return response;
    } else if (response.status == 404) {
        // no breaches
        return response.statusText;
    } else if (response.status == 400) {
        // bad request
        return response.statusText;
    } else {
        throw new Error(response.statusText);
    }
}

(я удалил console.log строк, которые были после return в каждой ветви, так как они были недоступны.)

...