Vue 基础学习(4):接口调用方式、异步、promise、fetch、axios、async 和 await

1、接口调用方式

  • 原生 ajax
  • 基于 jQuery 的 ajax
  • fetch
  • axios

2、异步

  • JavaScript的执行环境是 单线程
  • 所谓单线程,是指 JS 引擎中负责解释和执行 JavaScript 代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会阻塞其他任务。这个任务可称为主线程。
  • 异步模式可以一起执行多个任务
  • JS中常见的异步调用:
    • 定时器
    • ajax
    • 事件函数

3、promise

3.1 Promise 的基本使用

  • 主要解决异步深层嵌套的问题。
  • promise 提供了简洁的 API 使得异步操作更加容易。
  • console.log(Promise); Promise 对象
  • console.log(typeof Promise); 函数

Promise基本使用:

  • 我们使用 new 来构建一个 Promise,Promise 的构造函数接收一个参数,是函数,并且传入两个参数:resolve(表示异步操作执行成功后的回调函数),reject( 表示异步操作执行失败后的回调函数)。
  • Promise 实例生成以后,可以用 then 方法指定 resolved 状态和 reject 状态的回调函数。
  • 在 then 方法中,你也可以直接 return 数据而不是 Promise 对象,在后面的 then中就可以接收到数据了。

代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Promise 的基本使用</title>
</head>

<body>
    <script>
        // Promise 主要解决异步深层嵌套的问题
        // promise 提供了简洁的API  使得异步操作更加容易
        console.log(Promise);  // Promise对象
        console.log(typeof Promise); // 函数

        /*
         1. Promise基本使用
           我们使用new来构建一个Promise
           Promise的构造函数接收一个参数,是函数,并且传入两个参数:		
           resolve: 表示异步操作执行成功后的回调函数
           reject: 表示异步操作执行失败后的回调函数
        */

        var p = new Promise(function (resolve, reject) {
            // 2. 这里用于实现异步任务  setTimeout
            setTimeout(function () {
                var flag = true;
                if (flag) {
                    // 3. 正常情况
                    resolve('hello');
                } else {
                    // 4. 异常情况
                    reject('出错了');
                }
            }, 100);
        });

        //  5. Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数 
        //  在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了 
        p.then(function (data) {
            console.log(data);
        }, function (info) {
            console.log(info);
        });

    </script>
</body>

</html>

3.2 基于 Promise 发送 Ajax 请求并解决回调地狱问题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>基于Promise发送Ajax请求</title>
</head>

<body>
    <script>
        /*
            then参数中的函数返回值
        */
        function queryData(url) {
            // 1.1 创建一个Promise实例
            return new Promise(function (resolve, reject) {
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function () {
                    if (xhr.readyState != 4)
                        return;
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        // 1.2 处理正常的情况
                        resolve(xhr.responseText);
                    } else {
                        // 1.3 处理异常情况
                        reject('服务器错误');
                    }
                };
                xhr.open('get', url);
                xhr.send(null);
            });
        }
        // 发送一个ajax请求
        // queryData('http://localhost:3000/data')
        //     .then(function (data) {
        //         console.log(data);
        //     }, function (info) {
        //         console.log(info);
        //     });

        // 发送多个ajax请求并且保证顺序
        // 注意:这里需要开启一个服务器
        queryData('http://localhost:3000/data1')
            .then(function (data) {
                console.log(data);  // "Hello TOM!"
                // 1.4 想要继续链式编程下去 需要 return
                return queryData('http://localhost:3000/data2');
            })
            .then(function (data) {
                console.log(data);  // "Hello LISA!"
                return new Promise(function (resolve, reject) {
                    setTimeout(() => {
                        resolve(123);
                    }, 1000);
                });
            })
            // 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
            .then(function (data) {
                return 'hello';
            })
            .then(function (data) {
                console.log(data);  // "hello"
            })

    </script>
</body>

</html>

3.3 Promise 基本 API

(1)实例方法

  • .then():得到异步任务正确的结果。

  • .catch():获取异常信息。

  • .finally(): 成功与否都会执行(不是正式标准) 。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Promise常用API-实例方法</title>
</head>

<body>
    <script>
        /* Promise常用API-实例方法 */
        console.dir(Promise);
        function foo() {
            return new Promise(function (resolve, reject) {
                setTimeout(() => {
                    resolve('success');
                    // reject('error');
                }, 100);
            });
        };

        // foo()
        //     .then(function (data) {
        //         console.log(data);
        //     })
        //     .catch(function (data) {
        //         console.log(data);
        //     })
        //     .finally(function () {
        //         console.log('finished');
        //     });

        // 这两种写法是等效的
        foo()
            .then(function (data) {
                // 得到异步任务正确的结果
                console.log(data);   // "success"
            }, function (data) {
                // 获取异常信息
                console.log(data);
            })
            .finally(function () {
                // 成功与否都会执行(不是正式标准)
                console.log('finished');  // "finished"
            });
    </script>
</body>

</html>

(2)静态方法

  • .all()
  • Promise.all方法接受一个数组作参数,数组中的对象(p1、p2、p3)均为 promise 实例(如果不是一个 promise,该项会被用Promise.resolve转换为一个 promise)。它的状态由这三个 promise 实例决定。
  • .race()
  • Promise.race方法同样接受一个数组作参数。当p1, p2, p3中有一个实例的状态发生改变(变为fulfilledrejected),p 的状态就跟着改变。并把第一个改变状态的 promise 的返回值,传给 p 的回调函数。
<script>
    // console.dir(Promise)
    function queryData(url) {
        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState != 4) return;
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // 处理正常的情况
                    resolve(xhr.responseText);
                } else {
                    // 处理异常情况
                    reject('服务器错误');
                }
            };
            xhr.open('get', url);
            xhr.send(null);
        });
    };
    var p1 = queryData('http://localhost:3000/p1');
    var p2 = queryData('http://localhost:3000/p2');
    var p3 = queryData('http://localhost:3000/p3');
    Promise.all([p1, p2, p3]).then(function (result) {
        //   all 中的参数[p1,p2,p3]和返回的结果一一对应 ["Hello Tom!", "Hello Jerry!", "Hello Lisa!"]
        console.log(result);  //  ["Hello Tom!", "Hello Jerry!", "Hello Lisa!"]
    });
    Promise.race([p1, p2, p3]).then(function (result) {
        // 由于p1执行较快,Promise的then()将获得结果'p1'。p2,p3仍在继续执行,但执行结果将被丢弃。
        console.log(result);   // "Hello Tom!"
    });
</script>

4、Fetch API 的概述与基本使用

4.1 fetch

  • Fetch API 是新的 ajax 解决方案,Fetch会返回 Promise 。
  • fetch 不是 ajax 的进一步封装,而是原生js,没有使用XMLHttpRequest 对象

4.2 fetch 的基本使用

  • fetch 就是 ajax + Promise,使用的方式和 jquery 提供的 $.ajax() 差不多 。
  • fetc h默认的是 get 请求。
  • 用法: fetch(url, options).then()

用法:

<script>
    /*
    Fetch API 基本用法:
        fetch(url).then()
    第一个参数url:请求的路径,Fetch会返回Promise   
    所以我们可以使用then 拿到请求成功的结果
    */
    fetch('http://localhost:3000/fdata').then(function (data) {
        // text()方法属于fetch API的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
        return data.text();
    }).then(function (data) {
        // 在这个then里面我们能拿到最终的数据
        console.log(data);  // "Hello Fetch!"
    });
</script>

4.3 fetch API 中的 HTTP 请求

  • fetch(url, options).then()
  • HTTP协议,它给我们提供了很多的方法,如 POST,GET,DELETE,UPDATE,PATCH 和 PUT。
    • 默认的是 GET 请求。
    • 需要在 options 对象中指定对应的 method。
    • method:请求使用的方法 。
    • post 和普通请求的时候需要在 options 中设置请求头 headers 和 body。

实例:

<script>
    /*
    Fetch API调用接口传递参数
    */
    // 1. GET参数传递-传统URL 通过url ?的形式传参 
    fetch('http://localhost:3000/books?id=12', {
        // get 请求可以省略不写 默认的是GET
        method: 'get'
    }).then(function (data) {
        // 它返回一个Promise实例对象,用于获取后台返回的数据
        return data.text();
    }).then(function (data) {
        // 在这个then里面我们能拿到最终的数据
        console.log(data);
    });
    // 2. GET参数传递-restful形式的URL
    fetch('http://localhost:3000/books/13', {
        method: 'get'
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        console.log(data);
    });
    // // 3. DELETE请求方式参数传递
    fetch('http://localhost:3000/books/14', {
        method: 'delete'
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        console.log(data);
    });
    // 4.1 POST请求方式参数传递
    fetch('http://localhost:3000/books', {
        method: 'post',
        // 传递数据 
        body: 'uname=lili&pwd=123456',
        // 设置请求头
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        console.log(data);
    });
    // 4.2 POST请求方式参数传递
    fetch('http://localhost:3000/books', {
        method: 'post',
        body: JSON.stringify({
            uname: '筱雪',
            pwd: '123456'
        }),
        headers: {
            'Content-Type': 'application/json'
        }
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        console.log(data);
    });
    // 5.PUT请求方式参数传递
    fetch('http://localhost:3000/books/15', {
        method: 'put',
        body: JSON.stringify({
            uname: '小明',
            pwd: '123456'
        }),
        headers: {
            'Content-Type': 'application/json'
        }
    }).then(function (data) {
        return data.text();
    }).then(function (data) {
        console.log(data);
    });
</script>

服务器端部分路由:

app.get('/books', (req, res) => {
    res.send('传统的URL传递参数 id为:' + req.query.id);
});
app.get('/books/:id', (req, res) => {
    res.send('Restful形式的URL传递参数 id为:' + req.params.id);
});
app.delete('/books/:id', (req, res) => {
    res.send('DELETE请求传递参数 id为:' + req.params.id);
});
app.post('/books', (req, res) => {
    res.send('POST请求传递参数 用户名为:' + req.body.uname + '  密码为:' + req.body.pwd);
});
app.put('/books/:id', (req, res) => {
    res.send('PUT请求传递参数 修改id为:' + req.params.id + '  用户名为:' + req.body.uname + '  密码为' + + req.body.pwd);
});

4.4 fetch API 中的响应格式

  • 用 fetch 来获取数据,如果响应正常返回,我们首先看到的是一个 response 对象,其中包括返回的一堆原始字节,这些字节在收到后,需要我们通过调用方法将其转换为相应格式的数据,比如JSONBLOB或者TEXT等等。

实例:

 <script>
     /*
         Fetch响应结果的数据格式
     */
     fetch('http://localhost:3000/json').then(function (data) {
         // 将获取到的数据使用 json 转换对象
         // return data.json();
         // 将获取到的数据 转换成字符串 
         return data.text();
     }).then(function (data) {
         // console.log(typeof data);  // "object"
         // console.log(data);  // {uname: "小西", age: 13, gender: "female"}
         var obj = JSON.parse(data);  // 把字符串转化为JSON对象
         console.log(obj.uname, obj.age, obj.gender);  // 小西 13 female
     });
 </script>

服务器端路由:

app.get('/json', (req, res) => {
    res.json({
        uname: '小西',
        age: 13,
        gender: 'female'
    });
});

5、axios

  • 基于 promise 用于浏览器和 node.js 的 http 客户端。
  • 支持浏览器和 node.js 。
  • 支持 promise
  • 能拦截请求和响应。
  • 自动转换 JSON 数据
  • 能转换请求和响应数据。

5.1 axios 基础用法

  • get 和 delete请求传递参数
    • 通过传统的 url 以 ? 的形式传递参数
    • restful 形式传递参数
    • 通过 params 形式传递参数
  • post 和 put 请求传递参数
    • 通过选项传递参数
    • 通过 URLSearchParams 传递参数

实例:

 <script src="js/axios.js"></script>
 <script>
     /*
     axios请求参数传递
      */
     //  1. 发送get 请求
     axios.get('http://localhost:3000/adata').then(function (ret) {
         // 拿到 ret 是一个对象, 所有的对象都存在ret的 data 属性里面
         // 注意data属性是固定的用法,用于获取后台的实际数据
         console.log(ret.data);  // "Hello axios!"
         console.log(ret);  // Object
     });
     // 2. get 请求传递参数
     // 2.1  通过传统的url以 ? 的形式传递参数
     axios.get('http://localhost:3000/axios?id=10').then(function (ret) {
         console.log(ret.data);  // "axios get传递参数 id:10"
     });
     // 2.2 restful 形式传递参数
     axios.get('http://localhost:3000/axios/11').then(function (ret) {
         console.log(ret.data);  // "axios get(Restful)传递参数 id:11"
     });
     // 2.3 通过params形式传递参数 
     axios.get('http://localhost:3000/axios', {
         params: {
             id: 12
         }
     }).then(function (ret) {
         console.log(ret.data);  // "axios get传递参数 id:12"
     });
     // 3. axios delete请求传参  传参的形式和 get请求一样
     axios.delete('http://localhost:3000/axios', {
         params: {
             id: 13
         }
     }).then(function (ret) {
         console.log(ret.data);  // "axios delete传递参数 id:13"
     });
     // 4. axios的post请求
     // 4.1 通过选项传递参数
     axios.post('http://localhost:3000/axios', {
         uname: '小西',
         pwd: 123456
     }).then(function (ret) {
         console.log(ret.data);
     });
     // 4.2 通过 URLSearchParams 传递参数 
     var params = new URLSearchParams();
     params.append('uname', '小五');
     params.append('pwd', '12345');
     axios.post('http://localhost:3000/axios', params).then(function (ret) {
         console.log(ret.data);   // "axios post传递参数  用户名:小五 密码:12345"
     });
     // 5. axios put请求传参和post请求一样 
     axios.put('http://localhost:3000/axios/123', {
         uname: '小蓝',
         pwd: 123456789
     }).then(function (ret) {
         console.log(ret.data)
     });
 </script>

服务器端部分代码:

app.get('/adata', (req, res) => {
    res.send('Hello axios!');
});
app.get('/axios', (req, res) => {
    res.send('axios get传递参数 id:' + req.query.id);
});
app.get('/axios/:id', (req, res) => {
    res.send('axios get(Restful)传递参数 id:' + req.params.id);
});
app.delete('/axios', (req, res) => {
    res.send('axios delete传递参数 id:' + req.query.id)
});
app.post('/axios', (req, res) => {
    res.send('axios post传递参数  用户名:' + req.body.uname + ' 密码:' + req.body.pwd)
});
app.put('/axios/:id', (req, res) => {
    res.send('axiosput传递参数 id:' + req.params.id + '  用户名:' + req.body.uname + ' 密码:' + req.body.pwd)
});

5.2 axios 全局配置

  // 配置请求的基准URL地址(配置公共的请求头)
  axios.defaults.baseURL = 'http://localhost:3000/';
  // 配置请求头信息
  axios.defaults.headers['mytoken'] = 'hello';
  // 配置超时时间
  axios.defaults.timeout = 2500;
  // 配置公共的post的 Content-Type
  axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

5.3 axios 拦截器

  • 请求拦截器
    • 请求拦截器的作用是在请求发送前进行一些操作
      • 例如在每个请求体里加上token,统一做了处理,如果以后要改也非常容易。
  • 响应拦截器
    • 响应拦截器的作用是在接收到响应后进行一些操作
      • 例如在服务器返回登录状态失效,需要重新登录的时候,跳转到登录页。

实例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>axios拦截器</title>
</head>

<body>
    <script src="js/axios.js"></script>
    <script>
        /*
            axios拦截器
         */
        // 1. 请求拦截器 
        axios.interceptors.request.use(function (config) {
            console.log(config.url);  // http://localhost:3000/adata
            // 1.1 任何请求都会经过这一步 在发送请求之前做些什么
            config.headers.mytoken = '你好';
            // 1.2 这里一定要return 否则配置不成功
            return config;
        }, function (err) {
            // 1.3 对请求错误做点什么   
            console.log(err);
        });

        // 2. 响应拦截器 
        axios.interceptors.response.use(function (res) {
            console.log(res);
            // 2.1 在接收响应做些什么
            var data = res.data;
            return data;
        }, function (err) {
            // 2.2 对响应错误做点什么 
            console.log(err);
        });

        axios.get('http://localhost:3000/adata').then(function (data) {
            console.log(data)
        });
    </script>
</body>

</html>

6、async 和 await

  • async 作为一个关键字放到函数前面

    • 任何一个async函数都会隐式返回一个promise
  • await关键字只能在使用async定义的函数中使用

    • ​ await 后面可以直接跟一个 Promise 实例对象
    • ​ await 函数不能单独使用
  • async/await 让异步代码看起来、表现起来更像同步代码

  • async 和 await 好处:

    • async 搭配 await 是 ES7 提出的,它的实现是基于Promise。
  • 注意细节点:

    • await 函数不能单独使用,而且 async 函数返回的是一个 Promise 对象,可以使用 then 函数添加回调函数。当函数执行的时候,一旦遇到 await 函数就会先返回一个 Promise 对象,等到异步操作完成,再去执行后面的语句。
      实例:async 函数基本用法
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <script src="js/axios.js"></script>
    <script>
        /*
          async/await 处理异步操作:
          async函数返回一个Promise实例对象
          await后面可以直接跟一个Promise实例对象
        */

        // 1.async 基础用法
        // 1.1 async作为一个关键字放到函数前面
        async function queryData() {
            // 1.2 await关键字只能在使用async定义的函数中使用 await后面可以直接跟一个Promise实例对象
            var ret = await new Promise(function (resolve, reject) {
                setTimeout(() => {
                    resolve('你好');
                }, 1000);
            });
            // console.log(ret.data);
            return ret;
        }
        // 1.3 任何一个async函数都会隐式返回一个promise 我们可以使用then进行链式编程
        queryData().then(function (data) {
            console.log(data);
        });
    </script>
</body>

</html>

实例:async函数处理多个异步请求

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <script src="js/axios.js"></script>
    <script>
        /*
          async/await处理多个异步任务
        */
        axios.defaults.baseURL = 'http://localhost:3000';

        async function queryData() {
            // 添加await之后 当前的await返回结果之后才会执行后面的代码  
            var info = await axios.get('async1');
            // 让异步代码看起来、表现起来更像同步代码
            var ret = await axios.get('async2?info=' + info.data);
            return ret.data;
        }

        queryData().then(function (data) {
            console.log(data)
        });
    </script>
</body>

</html>
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值