浅谈 Fetch

浅谈 Fetch

技术杂谈小彩虹2021-07-18 19:05:0060A+A-

Fetch

参考: developers.google.com/web/updates…

现在可能还有一些很旧的程序还在使用XHR,类似下面的写法:

const request = new XMLHttpRequest()
request.responseType = 'json'
request.open('GET', '/url', true)
request.onload = () => {
  console.log(request.response)
}
request.onerror = () => {
  console.log('shits happen!')
}
request.send(null)

这样子使用XHR进行异步访问、读取资源显得很繁琐,相对比Fetch()允许你创建类似XHR的network访问,但是使用更简单而且干净的API,不需要多次回调并且记住XHR复杂的API。Fetch API底层是通过Promises实现。

XMLHttpRequest

一个相对完整的XMLHttpRequest至少需要监听两个事件(onload、onerror)来实现成功和失败的回调,以及调用open()和send()

function reqListener() {
  var data = JSON.parse(this.responseText);
  console.log(data);
}

function reqError(err) {
  console.log('Fetch Error :-S', err);
}

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

Fetch

一个简单的Fetch例子如下:

fetch('./api/some.json')
  .then(
    function(response) {
      if (response.status !== 200) {
        console.log('Looks like there was a problem. Status Code: ' +
          response.status);
        return;
      }

      // Examine the text in the response
      response.json().then(function(data) {
        console.log(data);
      });
    }
  )
  .catch(function(err) {
    console.log('Fetch Error :-S', err);
  });

Fetch的语法更加语义化、比较好理解。在上面的例子里我们先判断response的status码,如果是200我们才将response解析为JSON

fetch()请求返回的response是Stream对象,因此我们调用response.json时由于异步读取流对象所以返回的是一个Promise对象。

Fetch用async优化代码

由于Fetch底层是用Promise实现,我们可以直接用async来优化上面的代码,减少回调,使其更加语义化、容易理解

async function geturl(){
	try{
		let res = await fetch('./api/some.json')
		if(res.status == 200){
			console.log(await res.text())
		}
	} catch(err){
		console.log(err)
	}
}

Response元数据

在上面的例子里,我们了解了Response对象的status状态以及怎么把response对象转换为JSON对象,让我们来看看Response对象的其他元数据:

fetch('users.json').then(function(response) {
    console.log(response.headers.get('Content-Type'));
    console.log(response.headers.get('Date'));

    console.log(response.status);
    console.log(response.statusText);
    console.log(response.type);
    console.log(response.url);
});

Response类型

当我们发起一个Fetch请求时,返回的response响应会自带一个response.type属性(basic、cors、opaque)。response.type属性说明了异步资源的来源,同时还有相应的处理方式。

当我们发起一个同源请求时,response.type为basic,而且你可以从response读取全部信息。

如果我们访问一个非同源域名,并且有返回相应的CORs响应头时,那么该请求类型是cors。cors和basic很相似,就除了cors响应里你无法访问Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma

当我们对一个不同源的域名发起请求时,如果返回的响应头部没有CORS信息,那么这个response对应的类型就是opaque类型。一个opaque响应是无法读取返回的数据、状态,甚至无法确定这个请求是否成功。

我们可以自定义Fetch请求的模式,要求返回对应类型的响应,有以下几种响应:

  1. same-origin 只返回同源请求,其他类型会被reject
  2. cors 接收同源、非同源请求,返回有CORs头部的响应
  3. cors-with-forced-preflight 在发出请求前会先做一次安全性检查
  4. no-cors 用来发起没有CORS头部并且非同源请求,并且会返回opaque响应。但是目前这种类型只能在Service Worker里使用,在window.fetch里不能用
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
  .then(function(response) {
    return response.text();
  })
  .then(function(text) {
    console.log('Request successful', text);
  })
  .catch(function(error) {
    log('Request failed', error)
  });

承诺链

因为Fetch返回的response是基于Promise实现,所以我们可以像链条一样把几个Promise串接起来,如下所示:

function status(response) {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
  } else {
    return Promise.reject(new Error(response.statusText))
  }
}

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

fetch('users.json')
  .then(status)
  .then(json)
  .then(function(data) {
    console.log('Request succeeded with JSON response', data);
  }).catch(function(error) {
    console.log('Request failed', error);
  });

当然了,我们也可以用async进行代码优化

async function geturl(url){
	try {
		let res = await fetch(url)
		if(res.status >= 200 && res.status < 300){
			console.log('Request succeeded with JSON response', await res.json())
		}
	}catch (err){
		console.log(err)
	}
}

geturl('users.json')

Post请求

当我们使用Fetch发起Post请求时,需要手动设置method参数和body参数,如下:

fetch(url, {
    method: 'post',
    headers: {
      "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
  })
  .then(json)
  .then(function (data) {
    console.log('Request succeeded with JSON response', data);
  })
  .catch(function (error) {
    console.log('Request failed', error);
  });

如果没有显式指定method参数,那么默认Get请求

带Cookie发送请求

如果我们想要在异步请求中带上cookie参数,那么需要显式指定credentials参数:

fetch(url, {
  credentials: 'include'
})

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1

联系我们