fetch请求

结合之前的文章事件循环Event Loop_爬行者c的博客-CSDN博客 先理解JS异步的实现机制。

异步操作结果的处理方式一般会通过回调函数来实现。关于异步编程有以下几种。

Promise

内置类。异步编程,解决回调地域

参数:一个函数,该函数接收两个函数参数,resolve和reject,且必传

三种状态:pending(进行中,默认状态)、fulfilled/resolved(已成功,异步操作成功后)和rejected(已失败,异步操作失败后)

注:

  • 状态一旦修改就不能再改变,一旦执行就无法取消。pending-->resolved/rejected
  • then方法的参数期望是函数,传入非函数则会发生值穿透。
  • then异步执行,支持链式写法。
let promise = new Promise((resolve, reject) => {
  if (true) {
    // 将成功参数返回,供then方法使用
    resolve("value");
  } else {
    // 将失败参数返回,供then方法使用
    reject("error");
  }
});

//  then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。
promise.then(
  value => {
    // resolved时调用,value为resolve函数返回的参数
    console.log(value);
  },
  err => {
    // rejected时调用,err为reject函数返回的参数
    console.log(err);
  }
);
promise.catch(error => console.log(error));   //捕获错误

原型上的公有方法

Promise.prototype.then()
Promise.prototype.catch()
Promise.prototype.finally()

new Promise().then(res=>{}).catch(err=>{})

静态方法

Promise.resolve('a')
Promise.reject('a')
Promise.all([p1,p2,p3]]); //所有promise实例都为成功状态   返回值:新的Promise实例
Promise.race([p1,p2,p3]]); //同时发送多个请求,谁先有处理结果就返回,不管是成功还是失败(‘竞速’)

Generator函数

异步。分段执行。yield暂停执行,next恢复执行。缺点是并不能区分什么时候(在第一、第二...阶段)执行。

Generator 有两个区分于普通函数的部分:

  • 一是在 function 后面,函数名之前有个 * ;

  • 函数内部有 yield 表达式。

function* func(){
 console.log("one");
 yield '1';
 console.log("two");
 yield '2'; 
 console.log("three");
 yield '3'; 
}
var f = func();// 返回一个内部指针
// next()方法分阶段执行Generator函数,每次调用完返回一个对象
f.next(); // one  {value: '1', done: false}
f.next(); // two {value: '2', done: false}
// return 方法返回给定值,并结束遍历 Generator函数,未给定参数就返回undefined
f.return('over'); // {value: "over", done: true}
f.next(); // {value: undefined, done: true}

async函数

async 是 ES7 才有的与异步操作有关的关键字,和 Promise 和 Generator 有很大关联。

四种使用形式:

  • 函数声明: async function foo() {}
  • 函数表达式: const foo = async function() {}
  • 对象的方式: let obj = { async foo() {} }
  • 箭头函数: const foo = async () => {}

返回值:一个 Promise 对象,可以使用 then 方法添加回调函数。

await

用于等待一个 Promise 对象, 它只能在异步函数 async function 内部(async上下文)使用。主要的意图是用来等待 Promise 对象的状态被 resolved, 相当于promise.then。

function testAwait(){
   return new Promise((resolve) => {
       setTimeout(function(){
          console.log("testAwait");
          resolve();
       }, 1000);
   });
}
 
async function helloAsync(){
   await testAwait();
   console.log("helloAsync");
 }
helloAsync();
// testAwait
// helloAsync

await针对所跟不同表达式的处理方式:

  • Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。
  • 非 Promise 对象:直接返回对应的值,对象/字符串/布尔值/数值/普通函数

Ajax

 异步 JavaScript 和 XML。核心技术是XMLHttpRequest(XHR),创建一个Ajax对象要经过:

    //1.创建Ajax对象
    if(window.XMLHttpRequest){
       var xhr=new XMLHttpRequest();
    }else{
       var xhr=new ActiveXObject("Microsoft.XMLHTTP");
    }

    //2.连接服务器
    xhr.open('GET', url, true);  // false为同步,true为异步

    //3.发送
    xhr.send();

    //4.接收
    xhr.onreadystatechange=function (){
       if(xhr.readyState==4){
           if(xhr.status==200){
              //alert('成功了:'+xhr.responseText);
           }else{
              //alert('失败了');
           }
        }
    };

fetch

基于标准 Promise 实现,支持 async/await。脱离了XHR,属于原生JS,是window的一个方法。

相对于XHR发起请求的语法更加简洁。

 参数

url 请求地址

options 配置项对象,包括method、headers、body、credentials等参数

get请求

var result = fetch('url', {
        credentials: 'include',
        headers: {
            'Accept': 'application/json, text/plain, */*',
        },    
 });

post请求 

var result = fetch('/api/post', {
        method: 'POST',
        credentials: 'include',
        headers: {
            'Accept': 'application/json, text/plain, */*',
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        // 注意 post 时候参数的形式
        body: "a=1&b=2"
    });

 处理回调

fetch(url).then(response => {
    if (response.ok) {
       return response.json() // 解析为可读数据
    } else {
       return Promise.reject('请求失败')
    }
}) .then(data => console.log(data)) //执行结果是 resolve就调用then方法,,第二个then是真正的数据 
  .catch(e => console.log("error")) //执行结果是 reject就调用catch方法

结合async/await优化写法

async function() {
  try {
    let response = await fetch(url);
    let data = response.json();
    console.log(data);
  } catch (error) {
    console.log(' error');
  }
}

注意:

1、fetch只对网络故障或请求被阻止报错,不会拒绝http的错误状态,对404,500都当做成功的请求,将promise标记为resolve。可通过判断Response象中的ok是否为true,如果不是,用 Promise手动添加一个reject。

2、fetch默认不会带cookie,需要添加配置项 credentials: 'include'。

3、fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费。

4、fetch没有办法原生监测请求的进度,而XHR可以。

5、兼容性问题(ie完全不支持),针对不同的问题需要引入不同的库。

fetch封装

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',//为了在当前域名内自动发送 cookie , 必须提供这个选项
            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 {
        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)
                    }
                }
            }
        })
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值