浅谈 Fetch

Fetch 参考: https://developers.google.com...
如今可能还有一些很旧的程序还在使用XHR,相似下面的写法:php

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()web

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例子以下:json

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来优化上面的代码,减小回调,使其更加语义化、容易理解api

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响应里你没法访问cookie

Cache-Control

app

Content-Language

cors

Content-Type

异步

Expires

async

Last-Modified

Pragma

当咱们对一个不一样源的域名发起请求时,若是返回的响应头部没有CORS信息,那么这个response对应的类型就是opaque类型。一个opaque响应是没法读取返回的数据、状态,甚至没法肯定这个请求是否成功。
咱们能够自定义Fetch请求的模式,要求返回对应类型的响应,有如下几种响应:
same-origin 只返回同源请求,其余类型会被reject
cors 接收同源、非同源请求,返回有CORs头部的响应
cors-with-forced-preflight 在发出请求前会先作一次安全性检查
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'
})

转载于猿2048:→《浅谈 Fetch》

相关文章
相关标签/搜索