八 Vue学习 fetch请求

1:import {login, getAdminInfo} from '@/api/getData'(从api/getData.js中import login函数。)
  看一下以下的getData.js文件,其中export了login函数,因此其余地方能够调用。
import fetch from '@/config/fetch'

export const login = data => fetch('/admin/login', data, 'POST');

   继续看fetch.js函数:node

import { baseUrl } from './env'

export default async(url = '', data = {}, type = 'GET', method = 'fetch') => {
    type = type.toUpperCase();
    url = baseUrl + url;

    if (type == 'GET') {
        let dataStr = ''; //数据拼接字符串
        Object.keys(data).forEach(key => {
            dataStr += key + '=' + data[key] + '&';
        })

        if (dataStr !== '') {
            dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
            url = url + '?' + dataStr;
        }
    }

    if (window.fetch && method == 'fetch') {
        let requestConfig = {
            credentials: 'include',
            method: type,
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            mode: "cors",
            cache: "force-cache"
        }

        if (type == 'POST') {
            Object.defineProperty(requestConfig, 'body', {
                value: JSON.stringify(data)
            })
        }
        
        try {
            const response = await fetch(url, requestConfig);
            const responseJson = await response.json();
            return responseJson
        } catch (error) {
            throw new Error(error)
        }
    } else {  // 若是浏览器不支持fetch return new Promise((resolve, reject) => {
            let requestObj;
            if (window.XMLHttpRequest) {
                requestObj = new XMLHttpRequest();
            } else {
                requestObj = new ActiveXObject;
            }

            let sendData = '';
            if (type == 'POST') {
                sendData = JSON.stringify(data);
            }

            requestObj.open(type, url, true);
            requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            requestObj.send(sendData);

            requestObj.onreadystatechange = () => {
                if (requestObj.readyState == 4) {
                    if (requestObj.status == 200) {
                        let obj = requestObj.response
                        if (typeof obj !== 'object') {
                            obj = JSON.parse(obj);
                        }
                        resolve(obj)
                    } else {
                        reject(requestObj)
                    }
                }
            }
        })
    }
}

fetch:  传统 Ajax 指的是 XMLHttpRequest(XHR),如今已被 Fetch替代; Fetch API 是基于 Promise 设计,有必要先学习一下 Promisegit

XMLHttpRequest:是一个 API,它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个经过 URL 来获取数据的简单方式,而且不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。XMLHttpRequest 在 AJAX 中被大量使用;能够取回全部类型的数据资源,并不局限于 XML。并且除了 HTTP ,它还支持 file 和 ftp 协议。github

ActiveXObject:  与XMLHttpRequest差别很小,这二者是在不一样浏览器上使用的。json

IE里面:
new ActiveXObject("Msxml2.XMLHTTP")
new ActiveXObject("Microsoft.XMLHTTP")
Mozilla和Safari里面:
new XMLHttpRequest()

Fetch VS XHR(XMLHttpRequest):

XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式很是混乱,并且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。后端

Fetch 的出现就是为了解决 XHR 的问题,拿例子说明:api

使用 XHR 发送一个 json 请求通常是这样:promise

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';

xhr.onload = function() {
  console.log(xhr.response);
};

xhr.onerror = function() {
  console.log("Oops, error");
};

xhr.send();

使用 Fetch 后,顿时看起来好一点浏览器

fetch(url).then(function(response) {
  return response.json();
}).then(function(data) {
  console.log(data);
}).catch(function(e) {
  console.log("Oops, error");
});

使用 ES6 的 箭头函数 后:服务器

fetch(url).then(response => response.json())
  .then(data => console.log(data))
  .catch(e => console.log("Oops, error", e))

如今看起来好不少了,但这种 Promise 的写法仍是有 Callback 的影子,并且 promise 使用 catch 方法来进行错误处理的方式有点奇怪。不用急,下面使用 async/await 来作最终优化:babel

注:async/await 是很是新的 API,属于 ES7,目前尚在 Stage 1(提议) 阶段,这是它的完整规范。使用 Babel 开启 runtime 模式后能够把 async/await 无痛编译成 ES5 代码。也能够直接使用 regenerator 来编译到 ES5。

try {
  let response = await fetch(url);
  let data = response.json();
  console.log(data);
} catch(e) {
  console.log("Oops, error", e);
}
// 注:这段代码若是想运行,外面须要包一个 async function

duang~~ 的一声,使用 await 后,写异步代码就像写同步代码同样爽await 后面能够跟 Promise 对象,表示等待 Promise resolve() 才会继续向下执行,若是 Promise 被 reject() 或抛出异常则会被外面的 try...catch 捕获。

Promise,generator/yield,await/async 都是如今和将来 JS 解决异步的标准作法,能够完美搭配使用。这也是使用标准 Promise 一大好处。最近也把项目中使用第三方 Promise 库的代码所有转成标准 Promise,为之后全面使用 async/await 作准备。

另外,Fetch 也很适合作如今流行的同构应用,有人基于 Fetch 的语法,在 Node 端基于 http 库实现了 node-fetch,又有人封装了用于同构应用的 isomorphic-fetch

注:同构(isomorphic/universal)就是使先后端运行同一套代码的意思,后端通常是指 NodeJS 环境。

总结一下,Fetch 优势主要有:

  1. 语法简洁,更加语义化

  2. 基于标准 Promise 实现,支持 async/await

  3. 同构方便,使用 isomorphic-fetch

 

上面的代码的逻辑是:若是浏览器支持Fetch,就用fetch; 不然就用XHR

 


Let VS Var:
  • let : 变量只能声明一次
  • var : 变量能够屡次声明
let是ES6的新运算let的好处是当咱们写代码比较多的时候能够避免在不知道的状况下重复声明变量
相关文章
相关标签/搜索