您的位置:

fetch请求详解

fetch是一种替代XMLHttpRequest的网络请求API,它提供了一个简单、灵活并且具有强大功能的接口。在本文中,我们将从多个方面详细阐述fetch请求的相关知识。

一、fetch请求拦截

fetch请求可以通过拦截器来实现请求的拦截,可以在请求即将发送和响应已经获取之前拦截请求。拦截器可以帮助我们在请求发送之前更改请求参数、在请求结束之后处理响应结果。

以下是一个fetch请求拦截的示例代码:

fetch('/api/user', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
})
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});

function interceptor(fetchFunc) {
  return (url, options) => {
    console.log(`Intercepting request to ${url} with options`, options);
    return fetchFunc(url, options)
      .then(response => {
        console.log(`Intercepting response from ${url} with response`, response);
        return response;
      })
      .catch(error => {
        console.error(`Intercepting error from ${url} with error`, error);
        throw error;
      });
  };
}

fetch = interceptor(fetch);

在上面的代码中,我们定义了一个拦截器函数interceptor,并通过interceptor函数来对fetch方法进行拦截。在拦截器中,我们可以通过console.log方法来打印请求和响应内容。最后通过将拦截器函数返回后fetch方法调用指向了拦截器。

二、fetch请求携带cookie

默认情况下,fetch请求不会携带cookie信息。在需要携带cookie的请求中,我们需要在请求头中设置参数credentials为include。

以下是一个fetch请求携带cookie的示例代码:

fetch('/api/user', {
  method: 'GET',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
  }
})
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});
在上面的代码中,我们通过设置credentials为include来携带cookie信息,同时也设置了请求头的Content-Type参数。

三、fetch请求如何中断

fetch请求使用Promise实现,若需要中断请求可以通过AbortController来实现。

以下是一个fetch请求中断的示例代码:

const controller = new AbortController();
const signal = controller.signal;

fetch('/api/user', {
  method: 'GET',
  signal: signal,
  headers: {
    'Content-Type': 'application/json',
  }
})
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});

// 中断请求
controller.abort();
在上面的代码中,我们使用AbortController来实现请求的中断,通过定义controller.signal并将其作为fetch请求的参数传入来实现中断。

四、fetch请求和ajax的区别

fetch请求与ajax有很多相似之处,但是也有不同之处:

  • fetch请求使用Promise实现,ajax使用回调函数实现;
  • fetch请求默认不携带cookie信息,ajax默认携带cookie信息;
  • fetch请求支持跨域头,ajax需要使用jsonp实现跨域;
  • fetch请求使用可读流处理文件,ajax不能直接处理文件;
  • fetch请求使用状态码标记响应状态,ajax使用readyState和status标记响应状态。

五、fetch请求js文件

fetch请求可以用于获取js文件,获取到之后可以通过eval方法将文件内容解析为可执行的js代码。

以下是一个fetch请求获取js文件的示例代码:

fetch('/api/jsfile')
  .then(response => response.text())
  .then(data => {
    eval(data);
  });
在上面的代码中,我们通过fetch获取js文件,然后通过text方法将文件内容转为字符串,最后使用eval方法将获取到的js代码执行。

六、fetch请求封装

使用fetch的时候,我们经常会发现fetch的api操作没法满足我们的要求,比如fetch需要不同的headers、需要不同的parse方式等等,如果在业务代码中重复的使用fetch会让代码显得冗余,不够优雅。我们可以通过封装fetch,将复杂逻辑统一处理,让代码更为简洁优雅。

以下是一个fetch请求封装的示例代码:

const http = {
  get: (url, data, headers) => {
    return http.request(url, 'GET', data, headers);
  },
  post: (url, data, headers) => {
    return http.request(url, 'POST', data, headers);
  },
  request: async (url, method, data, headers) => {
    try {
      const response = await fetch(url, {
        method: method.toUpperCase(),
        headers: {
          'Content-Type': 'application/json',
          ...headers
        },
        body: JSON.stringify(data)
      });
      const json = await response.json();
      return json;
    } catch(error) {
      console.error(error);
    }
  }
};

http.get('/api/user', {}, {'Authorization': 'Bearer xxx'})
  .then(data => console.log(data))
  .catch(error => console.error(error));
在上面的代码中,我们定义了一个http对象,通过http对象的get和post方法来发送get和post请求。在http.request方法中,我们对请求进行了封装,支持自定义的headers、支持异步await等操作。

七、fetch请求跨域

fetch请求跨域需要跨域服务器设置Access-Control-Allow-Origin响应头,设置为允许请求的源地址。另一方面,由于fetch请求默认不携带cookie信息, 跨域请求需要设置credentials为include才能携带cookie。

以下是一个fetch请求跨域的示例代码:

fetch('http://cors-test.xxx.com/test.php', {
  method: 'GET',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
  }
})
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});
在上面的代码中,我们通过fetch请求跨域服务器test.php的数据,并携带cookie信息。

八、fetch请求参数

fetch请求可以通过URLSearchParams来构建请求参数,也可以直接在URL中传递参数。

以下是一个fetch请求参数的示例代码:

const params = new URLSearchParams();
params.append('name', 'Tom');
params.append('age', 18);

fetch('/api/user?' + params, {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
  }
})
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});
在上面的代码中,我们通过URLSearchParams来构建请求参数,然后将参数拼接在URL后面来发送请求。

九、fetch请求文件流

fetch请求可以通过ReadableStream接口来处理文件流,通过response.body获取响应的可读流数据。

以下是一个fetch请求文件流的示例代码:

fetch('/api/filestream')
  .then(response => {
    const reader = response.body.getReader();
  
    return new ReadableStream({
      start(controller) {
        function push() {
          reader.read().then(({ done, value }) => {
            if (done) {
              controller.close();
              return;
            }
            controller.enqueue(value);
            push();
          });
        }
        push();
      }
    })
  })
  .then(stream => new Response(stream))
  .then(response => response.blob())
  .then(blob => console.log(blob))
  .catch(error => console.error(error));
在上面的代码中,我们通过fetch响应的body获取到response的可读流,然后通过ReadableStream来将可读流转化为ReadableStream实例后,将其封装为Response实例,最后通过blob方法将response响应回来的文件数据转化为blob对象。

十、fetch请求api接口选取

根据要求,我们需要选取3~5个与fetch请求相关的api接口,以下是选取的接口:

  • fetch:发起网络请求
  • Headers:请求或响应头集合
  • Response:网络请求响应结果
  • Request:网络请求的信息,包含请求方法、请求地址及请求头等信息
  • FetchEvent:表示FetchEvent(网络请求事件)在服务工作线程中的事件状态

以上是fetch请求相关知识的详细阐述,fetch作为一种新一代的网络请求API,它具备了强大的功能并且易于使用。熟练掌握fetch的使用,有助于我们更好地进行网络请求相关开发。希望文章对您有所帮助。