【问题标题】:How to process fetch() response and still work asynchronously如何处理 fetch() 响应并仍然异步工作
【发布时间】:2018-10-23 04:53:11
【问题描述】:

我有一个对特定 API 执行大量 fetch() 调用的 JS 程序。我想将所有 fetch() 调用抽象到一个名为“apiService”的类中,这样我的代码将更具可读性。我希望 apiService 应用一些智能,然后通过以下方式将响应返回给调用者: - apiService 应该检查响应以查看是否存在错误,它必须始终以相同的方式处理。 - fetch() 有时会收到一个“res”,它是原始数据,应该按原样使用,有时它会收到需要 .then(res => res.json().then(res 应用所以它的 json可以返回一个对象。

所以我不能只从 apiService 执行“return fetch(...”),因为 apiService 需要处理一个或多个带有响应的 .then() 块。但我还需要返回一些导致调用的东西代码异步工作,不会阻塞和等待。

任何人都知道我可以如何构造 apiService 函数来处理 html 响应但也异步返回,即调用函数将在错误检查等之后接收结果对象。

【问题讨论】:

  • res 不是“原始数据”,它是一个响应对象。以及您想如何检查响应,如何区分 JSON 和其他内容?
  • 好的,谢谢。据我了解,我只能知道是否从 API 规范中预测 json、blob 或 text 等 - 还是有更优雅的方法来测试响应类型并做出相应的响应?
  • 嗯,您可以查看res 对象中的Content-type 标头...或者查看状态代码,如果它是200,它应该始终是记录在案的代码。跨度>
  • 内容类型不能保证存在,是吗?
  • 不,但我绝对不想使用不提供 API 的 API。它是基本的 HTTP 标头之一,每个适当的服务器应该设置它。 (没有内容类型,你只能res.arrayBuffer()并有良好的判断力)

标签: javascript asynchronous promise es6-promise


【解决方案1】:

所以我不能只从 apiService 执行“return fetch(...”),因为 apiService 需要处理一个或多个带有响应的 .then() 块。但我还需要返回一些导致调用的东西代码异步工作,不会阻塞和等待。

这让我感觉你可能有点误解了 promises。举个例子:

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

如您所见,通过在fetch 调用之后链接then,您实际上是在返回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')
})

【讨论】:

  • 谢谢 - 这原来是一个简单的解决方案。我用过:return fetch(furl, options).then(res => res.json({ // a }).then(res => { // b; return res})); 在点 // a 和 // b 我可以做任何我需要做的临时处理
【解决方案2】:

这里有一篇很好的文章,名为"Synchronous" fetch with async/await,它将为您分解。

简而言之

使用fetch()时可以使用await

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

首先我们等待请求完成,然后我们可以等待它完成(或失败),然后将结果传递给 json 变量。

完整的例子是使用async,因为没有它`await 将无法工作:

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

request();

【讨论】:

    【解决方案3】:

    我认为您可以使用 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

    【讨论】:

      【解决方案4】:

      您可以使用名为 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*/});
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 1970-01-01
        • 2015-11-19
        • 2019-05-28
        • 1970-01-01
        • 1970-01-01
        • 2023-02-02
        相关资源
        最近更新 更多