Как обработать ответ fetch () и по-прежнему работать асинхронно

1

У меня есть JS-программа, которая выполняет множество вызовов fetch() для определенного API. Я хочу абстрагировать все вызовы fetch() в один класс, называемый apiService, поэтому мой код будет более читабельным. Я хочу, чтобы apiService применял некоторый интеллект, а затем возвращал ответы вызывающему абоненту следующими способами: - apiService должен проверить ответ, чтобы увидеть, есть ли ошибки, которые он должен всегда обрабатывать одинаково. - fetch() иногда получает "res", который является необработанными данными и должен использоваться как есть, и иногда он получит json, который нуждается в.then(res => res.json(), затем (res применяется так, чтобы он может вернуть объект.

Поэтому я не могу просто выполнить "возврат fetch (..." из apiService, потому что apiService необходимо обработать один или несколько блоков.then() с ответом. Но мне также нужно вернуть что-то, что заставляет код вызова работать асинхронно, а не блокировать и ждать.

Кто-нибудь знает, как я мог бы структурировать функцию apiService для обработки html-ответов, но также возвращать асинхронно, то есть вызывающая функция получит объект результата после проверки ошибок и т.д.

  • 0
    res - это не «необработанные данные», это объект ответа. И как вы хотите проверить ответ, как вы можете отличить JSON от чего-то еще?
  • 0
    Да, спасибо. Насколько я понимаю, я могу знать только, ожидать ли json, blob, text и т. Д. Из спецификации API - или есть более элегантный способ проверить тип ответа и ответить соответствующим образом?
Показать ещё 3 комментария
Теги:
asynchronous
promise
es6-promise

4 ответа

2
Лучший ответ

Поэтому я не могу просто выполнить "возврат fetch (..." из apiService, потому что apiService необходимо обработать один или несколько блоков.then() с ответом. Но мне также нужно вернуть что-то, что заставляет код вызова работать асинхронно, а не блокировать и ждать.

Это дает мне ощущение, что вы, возможно, немного недопонимаете обещания. Возьмем следующий пример:

const doAsyncWork = () => fetch('somewhere').then(() => console.log('fetch is complete'))
// use the above function
doAsyncWork().then(() => console.log('used the fetching function'))

Выходом вышеуказанного кода будет

fetch is complete
used the fetching function

Как вы можете видеть, путем цепочки then после вызова fetch вы фактически возвращаете результат then, а не извлекаете. Еще один способ подумать о том, что вы действительно возвращаете, если вы позвонили

const result = a().b().c() // we are really returning the result of 'c()' here.

С учетом вышеизложенного вы можете определенно сделать что-то вроде:

const apiCall = loc => fetch(loc).then(res => {
  // do things with your response

  return res
})

apiCall('someEndpoint').then(finalRes => {
  console.log('this is called after fetch completed and response processed')
})
  • 0
    Спасибо - это оказалось простым решением. Я использовал: return fetch(furl, options).then(res => res.json({ // a }).then(res => { // b; return res})); В точках // a и // b я могу сделать любую промежуточную обработку, которая мне нужна
0

Существует хорошая статья об этом здесь, называемая "Синхронная" выборка с асинхронным/ожиданием, которая сломает ее для вас.

Вкратце:

Вы можете использовать await при использовании fetch():

const response = await fetch('https://api.com/values/1');
const json = await response.json();
console.log(json);

Сначала мы ждем завершения запроса. Тогда мы можем дождаться завершения (или сбоя), а затем передать результат переменной json.

Полный пример - использовать async, потому что "ожидание не будет работать без него:

const request = async () => {
    const response = await fetch('https://api.com/values/1');
    const json = await response.json();
    console.log(json);
}

request();
0

Вы можете использовать библиотеку под названием axios вместо того, чтобы беспокоиться о обещаниях и форматах данных самостоятельно.

Однако, если вы все еще хотите это сделать, используйте следующий способ.

вы можете использовать метод для создания таких обещаний.

 makeRequest(url, requestData) {

        const response = await fetch(url, requestData)
            .then(response => { console.info('network request successful to', url); return response.json() })
            .then(json => {
                console.info('response received for request', url, requestData, json)
                return json;
            })
            .catch(e => {
                console.error('error at request', url, requestData, e);
                return e
            });
        return response;
    }

и использовать обещания, подобные этому

makeRequest('someurl', {
            method: 'GET'
        }).then(response=>{/*Your logic*/}).catch(error=>{/*Your logic*/});
0

Я думаю, вы можете выполнить свое требование, используя Promise.all()

Вот вам пример.

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});

Для получения дополнительной информации вы можете обратиться:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Ещё вопросы

Сообщество Overcoder
Наверх
Меню