js新特性之网络编程0808

js新特性之网络编程

1.h5新增存储方案

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>18-H5新增存储方案</title>
    </head>
    <body>
    <button class="save">存点cookie</button>
    <button class="send">发送请求</button>
    
    <button class="btn1">保存</button>
    <button class="btn2">删除</button>
    <button class="btn3">修改</button>
    <button class="btn4">查找</button>
    <button class="btn5">清空</button>
    
    <script src="js/jquery-1.12.4.js"></script>
    <script src="myAjax2.js"></script>
    <script>
        /*
        1.什么是SessionStorage和LocalStorage
        和Cookie一样, SessionStorage和LocalStorage也是用于存储网页中的数据的
    
        2.Cookie、 SessionStorage、LocalStorage区别
        2.1生命周期(同一浏览器下)
        Cookie生命周期:         默认是关闭浏览器后失效, 但是也可以设置过期时间
        SessionStorage生命周期: 仅在当前会话(窗口)下有效,关闭窗口或浏览器后被清除, 不能设置过期时间
        LocalStorage生命周期:   除非被清除,否则永久保存
    
        2.2容量
        Cookie容量:         有大小(4KB左右)和个数(20~50)限制
        SessionStorage容量: 有大小限制(5M左右) http://dev-test.nemikor.com/web-storage/support-test/
        LocalStorage容量:   有大小限制(5M左右) http://dev-test.nemikor.com/web-storage/support-test/
    
        2.3网络请求
        Cookie网络请求:         每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题
        SessionStorage网络请求: 仅在浏览器中保存,不参与和服务器的通信
        LocalStorage网络请求:   仅在浏览器中保存,不参与和服务器的通信
    
        3.Cookie、 SessionStorage、LocalStorage应用场景
        Cookie:         判断用户是否登录
        LocalStorage:   购物车
        sessionStorage: 表单数据
    
        4.注意点:
        无论通过以上那种方式存储的数据, 切记不能将敏感数据直接存储到本地
        */
    
        $('.save').click(function () {
            document.cookie = "myName=it666;path=/;domain=127.0.0.1;";
        });
        $('.send').click(function () {
            ajax("18-cookie.php",
                {},
                3000,
                function (xhr) {
                    console.log("请求成功", xhr.responseText);
                }, function () {
                    console.log("请求失败");
                });
        });
      //进行以下操作时localStorage和 sessionStorage一样
        $('.btn1').click(function () {
            sessionStorage.setItem("name", "lnj");
            // sessionStorage.setItem("age", "34");
            //localStorage.setItem("name", "lnj");
        });
        $('.btn2').click(function () {
            sessionStorage.removeItem("name");
        });
        $('.btn3').click(function () {
            sessionStorage.setItem("name", "it666");
        });
        $('.btn4').click(function () {
            let value = sessionStorage.getItem("name");
            alert(value);
        });
        $('.btn5').click(function () {
            sessionStorage.clear();
        });
    
    </script>
    </body>
    </html>
    

2.同源策略

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>19-同源策略</title>
        <script src="js/jquery-1.12.4.js"></script>
    </head>
    <body>
    <button class="send">发送请求</button>
    <script>
        /*
        1.什么是同源策略?
        同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能
        所谓同源是指: 协议,域名,端口都相同,就是同源, 否则就是跨域
    
        http://www.it666.com:80/index.html
        协议: http/https/...
        一级域名: it666.com/itzb.com
        二级域名: www/study/edu/...
        端口号: 80/3306/...
    
        // 协议+一级域名+二级域名+端口号都相同, 所以同源
        http://www.it666.com:80/index.html
        http://www.it666.com:80/detail.html
    
        // 协议不同, 所以不同源, 是跨域
        http://www.it666.com:80/index.html
        https://www.it666.com:80/index.html
    
        // 一级域名不同, 所以不同源, 是跨域
        http://www.it666.com:80/index.html
        http://www.itzb.com:80/index.html
    
        // 二级域名不同, 所以不同源, 是跨域
        http://www.it666.com:80/index.html
        http://edu.it666.com:80/index.html
    
        // 端口号不同, 所以不同源, 是跨域
        http://www.it666.com:80/index.html
        http://www.it666.com:8090/index.html
    
        2.同源策略带来的影响
        在同源策略下, 浏览器只允许Ajax请求同源的数据, 不允许请求不同源的数据
        但在企业开发中, 一般情况下为了提升网页的性能, 网页和数据都是单独存储在不同服务器上的
        这时如果再通过Ajax请求数据就会拿不到跨域数据
    
        3.跨域解决方案
        jsonp
        document.domain+iframe
        location.hash + iframe
        window.name + iframe
        window.postMessage
        flash等第三方插件
        * */
    
        /*
        当前的网页地址: http://127.0.0.1:80/jQuery/Ajax/19-%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5.html
        请求的资源地址: http://127.0.0.1:80/jQuery/Ajax/19-SameOriginPolicy.php
    
        当前的网页地址: http://127.0.0.1:63342/jQuery/Ajax/19-%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5.html
        请求的资源地址: http://127.0.0.1:80/jQuery/Ajax/19-SameOriginPolicy.php
        */
        $('.send').click(function () {
            $.ajax({
                url:"19-SameOriginPolicy.php",
                success: function (msg) {
                    console.log(msg);
                },
                error: function () {
                    console.log("请求失败");
                }
            });
        });
    </script>
    </body>
    </html>
    
  • 后端

    • <?php
      echo 'it666.com'
      ?>
      

3.jsonp原理

  • <button>我是按钮</button>
    <script>
        /*
        1.什么是JSONP?
        JSONP让网页从别的地址(跨域的地址)那获取资料,即跨域读取数据
    
        2.JSONP实现跨域访问的原理
        2.1在同一界面中可以定义多个script标签
        2.2同一个界面中多个script标签中的数据可以相互访问
        2.3可以通过script的src属性导入其它资源
        2.4通过src属性导入其它资源的本质就是将资源拷贝到script标签中
        2.5script的src属性不仅能导入本地资源, 还能导入远程资源
        2.6由于script的src属性没有同源限制, 所以可以通过script的src属性来请求跨域数据
         */
        // let num = 666;
         function demo() {
             console.log("demo");
         }
    </script>
      <!--以下就是将20-jsonp.js里面的内容拷贝进去-->
    <script src="20-jsonp.js">
        // let num = 777;
        // function test() {
        //     console.log("test777");
        // }
    </script>
    
    <script src="http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php"></script>
    <script>
    
        // console.log(num);
        // test();
    
        // $("button").click(function () {
        //     alert("按钮被点击了");
        // });
    
        /*
        当前网页的地址: http://127.0.0.1:63342/jQuery/Ajax/20-jsonp%E5%8E%9F%E7%90%86.html
        远程资源的地址: http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php
        */
        console.log(num);
    </script>
    
  • 后端

    • <?php
      echo "let num = 789;";
      echo "demo(666);";
      ?>  
      

4.jsonp优化

  • <!--<script src="http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test"></script>-->
    <script>
        /*
        优化一
        1.在企业开发中通过JSONP来获取跨域的数据,
        一般情况下服务器返回的都不会是一个变量, 而是一个函数的调用
        */
    
        /*
        优化二
        2.当前服务器返回的函数调用名称写死了
        服务器返回函数叫什么名称, 我们本地就必须定义一个叫什么名称的函数
        */
        /*
        解决方案:
        通过URL参数的方式来动态指定函数名称
        在地址后边加个?cb=test"
        */
    
        /*
        优化三
        3.由于script标签默认是同步, 前面的script标签没有加载完数据, 后面的script标签就不会被执行
        所以请求数据的script标签必须放到后面
        */
        /*
        解决方案:
        通过JS动态创建script标签, 因为JS动态创建的script标签默认就是异步的,
        不用等到前面的标签加载完就可以执行后面的script标签
        */
      //下为优化3
        let oScript = document.createElement("script");
        oScript.src = "http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test";
        document.body.appendChild(oScript);
    
        function test(data) {
            console.log(data);
        }
    </script>
    <!--
    下为优化2
    <script src="http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test">
        // demo(666);
        // test(666);
    </script>
    -->
    
    
  • 后端

    • <?php
      $cb = $_GET['cb']; // test
      echo $cb."(666);"; // test(666);
      ?>
      

5.jQuery中的jsonp

  • <script src="js/jquery-1.12.4.js"></script>
    <script>
        /*
        当前网页的地址: http://127.0.0.1:63342/jQuery/Ajax/22-jQuery.html
        当前资源的地址: http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php
        */
        $.ajax({
            url: "http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php",
            data:{
                "teacher": "lnj",
                "age": 34
            },
            dataType: "jsonp", // 告诉jQuery需要请求跨域的数据
            jsonp: "cb",  // 告诉jQuery服务器在获取回调函数名称的时候需要用什么key来获取
            jsonpCallback: "lnj", // 告诉jQuery服务器在获取回调函数名称的时候回调函数的名称是什么
                              //需要注意的是jQuery中的jsonp不需要定义函数,会自己将回调函数中的                              参数返回给msg
            success: function (msg) {
                console.log(msg);
            }
        });
    </script>
    
  • 后端

    • <?php
      // 0.拿到传递过来的数据
      $teacher = $_GET["teacher"];
      $age = $_GET["age"];
      $arr = array("name"=>$teacher, "age"=>$age);
      $data = json_encode($arr);
      
      // 1.拿到回调函数的名称
      //$cb = $_GET["callback"]; // jQuery112406520384710124194_1559732574283
      $cb = $_GET["cb"]; // lnj
      // 2.返回数据
      //echo $cb."(666);"; // jQuery112406520384710124194_1559732574283(666);
      echo $cb."(".$data.");"; // lnj(666);
      ?>
      

6.jsonp封装(自己实现一个jsonp)

  • function obj2str(obj) {
        // 生成随机因子
        obj.t = (Math.random() + "").replace(".", "");
        let arr = [];
        for(let key in obj){
            //encodeURI用于将中文转换为什么编码
            arr.push(key + "=" + encodeURI(obj[key]));
        }
        let str = arr.join("&");
        // console.log(str);
        return str;
    }
    function myJSONP(options) {
        options = options || {};
        // http://127.0.0.1/jQuery/Ajax/22-jsonp.php?cb=lnj&teacher=lnj&age=34&_=1559735634387
        // http://127.0.0.1/jQuery/Ajax/22-jsonp.php?cb=lnj&teacher=lnj&age=34&t=08520581619221432
        // 1.生成URL地址
        let url = options.url;
        if(options.jsonp){
            url += "?" + options.jsonp + "=";
        }else{
            url += "?callback=";
        }
    
        let callbackName = ("jQuery" + Math.random()).replace(".", "");
        if(options.jsonpCallback){
            callbackName = options.jsonpCallback;
            url += options.jsonpCallback;
        }else{
            // console.log(callbackName);
            url += callbackName;
        }
        if(options.data){
            let str = obj2str(options.data);
            url += "&" + str;
        }
        // console.log(url);
    
        // 2.获取跨域的数据
        let oScript = document.createElement("script");
        oScript.src = url;
        document.body.appendChild(oScript);
    
        // 3.定义回调函数
        window[callbackName] = function (data) {
            // 删除已经获取了数据的script标签
            document.body.removeChild(oScript);
            // 将获取到的数据返回给外界
            options.success(data);
        }
    }
    
  • html调用
    • myJSONP({
          url: "http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php",
          data:{
              "teacher": "lnj",
              "age": 34
          },
          jsonp: "cb",  // 告诉jQuery服务器在获取回调函数名称的时候需要用什么key来获取
          jsonpCallback: "lnj", // 告诉jQuery服务器在获取回调函数名称的时候回调函数的名              称是什么
          success: function (msg) {
              console.log(msg);
          }
      });
      

7.....

  • 了解静态数据和动态数据
  • 了解程序进程和线程之间的关系
  • 了解串行和并行

8.js串行和事件循环

  • <script>
        /*
        1.JS是单线程的
        所以JS中的代码都是串行的, 前面没有执行完毕后面不能执行
        */
        /*
        2.同步代码和异步代码
        除了"事件绑定的函数"和"回调函数"以外的都是同步代码
    
        2.1程序运行会从上至下依次执行所有的同步代码
        2.2在执行的过程中如果遇到异步代码会将异步代码放到事件循环中
        2.3当所有同步代码都执行完毕后, JS会不断检测 事件循环中的异步代码是否满足条件
        2.4一旦满足条件就执行满足条件的异步代码
        (就如下边写的那个模拟代码)
        * */
        /*
        2.为什么JS是单线程的?
        avaScript的单线程,与它的用途有关。
        作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。
        这决定了它只能是单线程,否则会带来很复杂的同步问题。
    
        例如: 如果JS是多线程的
        现在有一个线程要修改元素中的内容, 一个线程要删除该元素, 这时浏览器应该以哪个线程为准?
        */
        console.log("1"); // 同步代码
        setTimeout(function () { // 异步代码
            console.log("2");
        }, 500);
        console.log("3"); // 同步代码
        alert("666"); // 同步代码
        // 1 / 3 / 2
        //先执行同步代码,输出1 3 弹出666 然后将异步代码添加到一个数组中,这时如果不将666关闭,那么就说明   那个同步代码没有执行完毕,就不会输出2,这也证明了js是单线程的
        /*
        // 系统添加代码模拟
        let arr = [setTimeout(function () { // 异步代码
            console.log("2");
        }, 500)];
        事件循环
        let index = 0;
        let length = arr.length;
        while(true){
            let item = arr[index];
            if(item.time === 500){
                执行异步代码
            }
            index++;
            if(index === length){
                index = 0;
            }
        }
        扩展阅读: https://segmentfault.com/a/1190000015042127
         */
    </script>
    

9.promise

9.1 promise基本概念
  • <script>
        /*
        1.什么是promise?
        promise是ES6中新增的异步编程解决方案, 在代码中的表现是一个对象
        */
    
        // 需求: 从网络上加载3个资源, 要求加载完资源1才能加载资源2, 加载完资源2才能加载资源3
        // 前面任何一个资源加载失败, 后续资源都不加载
    
        /*
        我们用定时器模拟一下上面的需求
        function request(fn) {
            setTimeout(function () {
                fn("拿到的数据");
            }, 1000);
        }
        request(function (data) {
            console.log(data, 1);
            request(function (data) {
                console.log(data, 2);
                request(function (data) {
                    console.log(data, 3);
                });
            });
        });
        */
        /*
        2.promise作用
        企业开发中为了保存异步代码的执行顺序, 那么就会出现回调函数层层嵌套
        如果回调函数嵌套的层数太多, 就会导致代码的阅读性, 可维护性大大降低
        promise对象可以将异步操作以同步流程来表示, 避免了回调函数层层嵌套(回调地狱)
        * */
        function request() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    resolve("拿到的数据");
                }, 1000);
            });
        }
        request().then(function (data) {
            console.log(data, 1);
            return request();
        }).then(function (data) {
            console.log(data, 2);
            return request();
        }).then(function (data) {
            console.log(data, 3);
        });
    </script>
    
9.2promise基本使用
  • <script>
        /*
        1.什么是Promise?
        Promise是ES6中新增的一个对象,
        通过Promise就可以实现 用同步的流程来表示异步的操作
        通过Promise就可以 避免回调函数层层嵌套(回调地狱)问题
    
        2.如何创建Promise对象?
        new Promise(function(resolve, reject){});
        promise对象不是异步的, 只要创建promise对象就会立即执行存放的代码
    
        3.Promise是如何实现 通过同步的流程来表示异步的操作的?
        promise对象是通过状态的改变来实现的, 只要状态发生改变就会自动触发对应的函数
              如下所说,当通过在promise中调用函数,转为不同的状态,在外边通过状态的不同会调用不同的函数.
    
        4.Promise对象三种状态
        pending:   默认状态,只要没有告诉promise任务是成功还是失败就是pending状态
        fulfilled(resolved): 只要调用resolve函数, 状态就会变为fulfilled, 表示操作成功
        rejected:  只要调用rejected函数, 状态就会变为rejected, 表示操作失败
        注意点: 状态一旦改变既不可逆, 既从pending变为fulfilled, 那么永远都是fulfilled
                                      既从pending变为rejected, 那么永远都是rejected
    
        5.监听Promise状态改变
        我们还可以通过函数来监听状态的变化
        resolved --> then()
        rejected --> catch()
        */
        // console.log("1");
        let promise = new Promise(function (resolve, reject) {
            console.log("2");//会立即输出  对应上面2
            reject();//会调用catch()函数   对应345
            // resolve();
        });
        // console.log(promise);
        promise.then(function () {
            console.log("then");
        });
        promise.catch(function () {
            console.log("catch");
        });
    </script>
    
9.3 then方法
  • <script>
        /*
        0.then方法
        then方法接收两个参数,
        第一个参数是状态切换为成功时的回调,
        第二个参数是状态切换为失败时的回调
        * */
        //以下会打印成功
        let promise = new Promise(function (resolve, reject) {
            // resolve(); // 将状态修改为成功
            reject(); // 将状态修改为失败
        });
        promise.then(function () {
            console.log("成功");
        }, function () {
            console.log("失败");
        });
        
    
        /*
        1.then方法
        在修改promise状态时, 可以传递参数给then方法中的回调函数
        */
        
        // resolve = success, reject = error;
        //以下会输出失败aaa
        let promise = new Promise(function (resolve, reject) {
            // resolve("111"); // 将状态修改为成功 success("111");
            reject("aaa"); // 将状态修改为失败  error("aaa");
        });
        promise.then(function (data) {
            console.log("成功", data);
        }, function (data) {
            console.log("失败", data);
        });
        //原理如下
        function success(data) {
            console.log(data);
        }
        function error(data) {
            console.log(data);
        }
        promise.then(success, error);
        
    
        /*
        2.then方法
        同一个promise对象可以多次调用then方法,
        当该promise对象的状态变化时所有then方法都会被执行
        */
        //以下会输出 失败1 失败2
        let promise = new Promise(function (resolve, reject) {
            // resolve(); // 将状态修改为成功
            reject(); // 将状态修改为失败
        });
        promise.then(function () {
            console.log("成功1");
        }, function () {
            console.log("失败1");
        });
        promise.then(function () {
            console.log("成功2");
        }, function () {
            console.log("失败2");
        });
        
    
        /*
        3.then方法
        then方法每次执行完毕后会返回一个新的promise对象
        */
        //以下 p2是一个promise对象 但是promise === p2)为false
        let promise = new Promise(function (resolve, reject) {
            resolve(); // 将状态修改为成功
            // reject(); // 将状态修改为失败
        });
        let p2 = promise.then(function () {
            console.log("成功1");
        }, function () {
            console.log("失败1");
        });
        console.log(p2);
        console.log(promise === p2);
        
    
        /*
        4.then方法
        可以通过上一个promise对象的then方法给下一个promise对象的then方法传递参数
        注意点:
        无论是在上一个promise对象成功的回调还是失败的回调传递的参数,
        都会传递给下一个promise对象成功的回调
        */
        //以下会输出 失败1 aaa 成功2 bbb
        let promise = new Promise(function (resolve, reject) {
            // resolve("111"); // 将状态修改为成功
            reject("aaa"); // 将状态修改为失败
        });
        let p2 = promise.then(function (data) {
            console.log("成功1", data);
            return "222";
        }, function (data) {
            console.log("失败1", data);
            return "bbb";
        });
        p2.then(function (data) {
            console.log("成功2", data);
        }, function (data) {
            console.log("失败2", data);
        });
        
    
        /*
        5.then方法
        如果then方法返回的是一个Promise对象, 那么会将返回的Promise对象的
        执行结果中的值传递给下一个then方法
        */
        //以下输出 成功1 111 失败2 bbb
        let promise = new Promise(function (resolve, reject) {
            resolve("111"); // 将状态修改为成功
            // reject("aaa"); // 将状态修改为失败
        });
        let ppp = new Promise(function (resolve, reject) {
            // resolve("222"); // 将状态修改为成功
            reject("bbb"); // 将状态修改为失败
        });
        let p2 = promise.then(function (data) {
            console.log("成功1", data);
            return ppp;
        }, function (data) {
            console.log("失败1", data);
            return "bbb";
        });
        p2.then(function (data) {
            console.log("成功2", data);
        }, function (data) {
            console.log("失败2", data);
        });
    </script>
    
    
9.4 catch方法
  • <script>
        /*
        0.catch方法
        catch 其实是 then(undefined, () => {}) 的语法糖,就是后边的能传递参数
        */
        
        let promise = new Promise(function (resolve, reject) {
            // resolve(); // 将状态修改为成功,catch方法找不到的
            reject(); // 将状态修改为失败
        });
        promise.catch(function () {
            console.log("abc");
        });
       
    
        /*
        2.catch方法
        注意点: 如果需要分开监听, 也就是通过then监听成功通过catch监听失败
        那么必须使用链式编程, 否则会报错
        */
        
        let promise = new Promise(function (resolve, reject) {
            // resolve(); // 将状态修改为成功
            reject(); // 将状态修改为失败
        });
        promise.then(function () {
            console.log("成功");
        }).catch(function () {
            console.log("失败");
        });
      /*
      以下会报错
        promise.then(function () {
            console.log("成功");
        });
        promise.catch(function () {
            console.log("失败");
        });
      */    
    
        /*
        了解一下报错的原因
        3.catch方法
        不使用链式编程报错的原因是
        1.如果promise的状态是失败, 但是没有对应失败的监听就会报错
        2.then方法会返回一个新的promise, 新的promise会继承原有promise的状态
        3.如果新的promise状态是失败, 但是没有对应失败的监听也会报错
        也就是说下边的p2是then方法返回的promise,而且promise的状态是失败,但是没有监听p2,所以会报错
        */
        let promise = new Promise(function (resolve, reject) {
            // resolve(); // 将状态修改为成功
            reject(); // 将状态修改为失败
        });
        let p2 = promise.then(function () {
            console.log("成功");
        });
        console.log(p2);
        promise.catch(function () {
            console.log("失败1");
        });
        p2.catch(function () {
            console.log("失败2");
        });
        
        /*
        与then方法的不同
      .catch方法
        和then方法第二个参数的区别在于, catch方法可以捕获上一个promise对象then方法中的异常
        */
        let promise = new Promise(function (resolve, reject) {
            resolve();
        });
        promise.then(function () {
            console.log("成功");
            xxx
        }).catch(function (e) {
            console.log("失败", e);//会打印错误信息
        });
    </script>
    
9.5 异常处理
  • <script>
        /*
        1.JS中的异常
        简单粗暴就是有错误出现
        由于JS是单线程的, 编写的代码都是串行的,
        所以一旦前面代码出现错误,程序就会被中断, 后续代码就不会被执行
    
        2.JS中的异常处理
        2.1自身编写代码问题, --> 手动修复BUG
        2.2外界原因问题, --> try{}catch{}
        对于一些可预见的异常, 我们可以使用try{}catch{}来处理,
    
        3.JS中如何进行异常处理
        利用try{}catch{}来处理异常可以保证程序不被中断, 也可以记录错误原因以便于后续优化迭代更新
        try {
            可能遇到的意外的代码
        }
        catch(e) {
            捕获错误的代码块
        }
        */
        // function say(){
        //     console.log("say");
        // }
        console.log("1");
        try {//这样就算没有定义say函数也会继续执行代码
            say(); 
        }catch (e) {
            console.log(e);
        }
        console.log("2");
    </script>
    
9.6 promise练习
  • <script>
        /*
        需求:
        一次加载一张图片添加到body中. 前面图片加载失败后面图片不加载
        */
        let arr = [
            "http://www.it666.com/files/system/block_picture_1555415767.png",
            "http://www.it666.com/files/system/block_picture_1555422597.jpg",
            "http://wwww.it666.com/files/system/block_picture_1555419713.jpg"
        ];
        function loadImage(url) {
            return new Promise(function (resolve, reject) {
               let oImg = new Image();
               oImg.src = url;
               oImg.onload = function () {
                   resolve(oImg);
               }
               oImg.onerror = function () {
                   reject("图片加载失败");
               }
            });
        }
        
        loadImage(arr[0]).then(function (oImg) {
            // console.log(oImg);
            console.log("1");
            document.body.appendChild(oImg);
            return loadImage(arr[1]);
        }).then(function (oImg) {
            console.log("2");
            // console.log(oImg);
            document.body.appendChild(oImg);
            return loadImage(arr[2]);
        }).then(function (oImg) {
            console.log("3");
            // console.log(oImg);
            document.body.appendChild(oImg);
        }).catch(function (msg) {
            console.log(msg);
        });
    </script>
    
9.7 promise-all方法
  • <script>
        /*
        需求:
        1.无序加载图片, 每加载成功一张就添加一张
        2.无序加载图片, 只有所有图片都加载成功才添加, 有一张图片失败都不添加
        */
        //1实现
        let arr = [
            "http://www.it666.com/files/system/block_picture_1555415767.png",
            "http://www.it666.com/files/system/block_picture_1555422597.jpg",
            "http://www.it666.com/files/system/block_picture_1555419713.jpg"
        ];
        function loadImage(url) {
            return new Promise(function (resolve, reject) {
                let oImg = new Image();
                let time = Math.random() * 1000;
                // console.log(time);
                setTimeout(function () {
                    oImg.src = url;
                }, time);
                // oImg.src = url;
                oImg.onload = function () {
                    resolve(oImg);
                }
                oImg.onerror = function () {
                    reject("图片加载失败了");
                }
            });
        }
    
        /*
        Promise的all静态方法:
        1.all方法接收一个数组,
        2.如果数组中有多个Promise对象,只有都成功才会执行then方法,
        并且会按照添加的顺序, 将所有成功的结果重新打包到一个数组中返回给我们
        3.如果数组中不是Promise对象, 那么会直接执行then方法
    
        应用场景: 批量加载, 要么一起成功, 要么一起失败
        * */
        /*
        let p1 = new Promise(function (resolve, reject) {
            // resolve("111");
            reject("aaa");
        });
        let p2 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve("222");
            }, 5000);
        });
        let p3 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve("333");
            }, 3000);
        });
        Promise.all([p1, p2, p3]).then(function (result) {
            console.log("成功", result);
        }, function (err) {
            console.log("失败", err);
        });
        */
      //2实现
        Promise.all([loadImage(arr[0]), loadImage(arr[1]),loadImage(arr[2])])
            .then(function (result) {
                // console.log(result);
                result.forEach(function (oImg) {
                    document.body.appendChild(oImg);
                });
            })
            .catch(function (e) {
                console.log(e);
            });
    </script>
    
    

10.fetch网络请求

  • <script>
        /*
        1.什么是fetch?
        和Ajax一样都是用于请求网络数据的
        fetch是ES6中新增的, 基于Promise的网络请求方法
    
        2.fetch基本使用
        fetch(url, {options})
        .then()
        .catch();
    
        http://127.0.0.1/jQuery/Ajax/41.php
        */
        
        /*
        fetch("http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34", {
        //get请求如果发送数据直接写在url后边
            method: "get"
        }).then(function (res) {
            // console.log(res.text());
            // return res.text();
            return res.json();//可以将返回的数据转换成一个json对象
        }).then(function (data) {
            console.log(data);
            console.log(typeof data);
        }).catch(function (e) {
            console.log(e);
        });
        */
        fetch("http://127.0.0.1/jQuery/Ajax/41.php", {
            method: "post",
            body: JSON.stringify({teacher:"zq", age:666})
            //post传参如上
        }).then(function (res) {
            // console.log(res.text());
            // return res.text();
            return res.json();
        }).then(function (data) {
            console.log(data);
            console.log(typeof data);
        }).catch(function (e) {
            console.log(e);
        });
    </script>
    

11.axios插件的使用

  • <script src="js/axios.js"></script>
    <script>
        /*
        1.什么是axios?
        Axios 是一个基于 promise 的 HTTP 库网络请求插件
    
        2.axios特点
        2.1可以用在浏览器和 node.js 中
        2.2支持 Promise API
        2.3自动转换 JSON 数据
        2.4客户端支持防御 XSRF
        */
        
        // axios.get("http://127.0.0.1/jQuery/Ajax/41.php")
        // axios.get("http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34")
        axios.post("http://127.0.0.1/jQuery/Ajax/41.php", {
            teacher: "lnj",
            age: 666
        })
            .then(function (res) {
                console.log(res.data);
            })
            .catch(function (e) {
                console.log(e);
            });
        
    
        /*
        3.全局的 axios 默认值
        在企业开发中项目分为 :开发阶段和部署阶段, 这两个阶段项目存储的位置是不同的
        项目上线前存储在企业内部测试服务器上, 项目上线后存储在企业正式服务器上
        所以如果每次请求都将请求的地址写在请求中, 那么项目上线时需要大量修改请求地址
        为了解决这个问题, 我们可以配置一个全局URL根地址, 项目上线时只需要修改根地址即可
        例如: 上线前地址是: http://127.0.0.1/jQuery/Ajax/41.php
              上线后地址是: http://192.199.13.14/jQuery/Ajax/41.php
        */
        axios.defaults.timeout = 2000;
        axios.defaults.baseURL = "http://127.0.0.1";
        axios.post("/jQuery/Ajax/41.php", {
            teacher: "lnj",
            age: 666
        })
            .then(function (res) {
                console.log(res.data);
            })
            .catch(function (e) {
                console.log(e);
            });
    </script>
    

12.Symbol

12.1 Symbol基本概念
  • <script>
        /*
        1.什么Symbol?
        Symbol是ES6中新增的一种数据类型, 被划分到了基本数据类型中
        基本数据类型: 字符串、数值、布尔、undefined、null、Symbol
        引用数据类型: Object
    
        2.Symbol的作用
        用来表示一个独一无二的值
    
        3.如果生成一个独一无二的值?
        let xxx = Symbol();
        */
        /*
        4.为什么需要Symbol?
        在企业开发中如果需要对一些第三方的插件、框架进行自定义的时候
        可能会因为添加了同名的属性或者方法, 将框架中原有的属性或者方法覆盖掉
        为了避免这种情况的发生, 框架的作者或者我们就可以使用Symbol作为属性或者方法的名称
    
        5.如何区分Symbol?
        在通过Symbol生成独一无二的值时可以设置一个标记如  Symbol("name");
        这个标记仅仅用于区分, 没有其它任何含义
        */
        // let xxx = Symbol();
        // let yyy = Symbol();
        // console.log(xxx === yyy);
    
        /*
        let obj = {
            name: "lnj",
            say: function () {
                console.log("say");
            }
        }
        obj.name = "it666";
        console.log(obj.name);
        obj.say = function () {
            console.log("test");
        }
        obj.say();
        */
        let name = Symbol("name");
        let say = Symbol("say");
        let obj = {
            // 注意点: 如果想使用变量作为对象属性的名称, 那么必须加上[]
            [name]: "lnj",
            [say]: function () {
                console.log("say");
            }
        }
        // obj.name = "it666";
        obj[Symbol("name")] = "it666"; //不会覆盖框架里定义的
        console.log(obj);
    </script>
    
12.2 Symbol注意点
  • <script>
        // 1.通过Symbol生成独一无二值时需要在后面加上(), 但是前面不能加new, 因为它不是引用类型
        let xxx = Symbol(); // 正确
        let xxx = new Symbol(); // 错误
    
        // 2.通过Symbol生成独一无二值时传入的字符串仅仅是一个标记, 方便我们阅读代码, 没有其它任何意义
        // let xxx = Symbol("name");
    
        // 3.做类型转换的时候不能转换成数值
        let xxx = Symbol("name");
        console.log(String(xxx));
        console.log(Boolean(xxx));
        console.log(Number(xxx));//报错
    
        // 4.不能做任何运算
        let xxx = Symbol("name");
        console.log(xxx + "abc");
        console.log(xxx + 123);
    
        // 5.Symbol生成的值作为属性或方法名称时, 一定更要保存下来, 否则后续无法使用
       // let name = Symbol("name");
        let obj = {
             // [name]: "lnj"
             [Symbol("name")]: "it666"
         }
         //console.log(obj[name]);
        console.log(obj[Symbol("name")]);//拿不到,有创建了一个新的独一无二的值
    
        // 6.for循环无法遍历出Symbol的属性和方法
        let name = Symbol("name");
        let say = Symbol("say");
        let obj = {
            // 注意点: 如果想使用变量作为对象属性的名称, 那么必须加上[]
            [name]: "lnj",
            [say]: function () {
                console.log("say");
            },
            age: 34,
            gender: "man",
            hi: function () {
                console.log("hi");
            }
        }
        for(let key in obj){
            console.log(key); 
        }
        //通过下面这个方法来获取symbol属性 ,会返回一个数组
        console.log(Object.getOwnPropertySymbols(obj));
    </script>
    

13.Iterator

13.1 基本概念
  • <script>
        /*
        1.什么是Iterator?
        Iterator又叫做迭代器, 是一种接口
        这里的接口和现实中接口一样, 是一种标准一种规范
        例如: 电脑的USB接口有电脑USB接口的标准和规范, 正式因为有了标准和规范
              所以A厂商生成的USB线可以插到B厂商电脑的USB接口上
    
        它规定了不同数据类型统一访问的机制, 这里的访问机制主要指数据的遍历
        在ES6中Iterator接口主要供for...of消费
    
        2.默认情况下以下数据类型都实现的Iterator接口
        Array/Map/Set/String/TypedArray/函数的 arguments 对象/NodeList 对象
        */
        /*
        1.只要一个数据已经实现了Iterator接口, 那么这个数据就有一个叫做[Symbol.iterator]的属性
        2.[Symbol.iterator]的属性会返回一个函数
        3.[Symbol.iterator]返回的函数执行之后会返回一个对象
        4.[Symbol.iterator]函数返回的对象中又一个名称叫做next的方法
        5.next方法每次执行都会返回一个对象{value: 1, done: false}done为false说明还没有执行完
        6.这个对象中存储了当前取出的数据和是否取完了的标记
        */
        
        let arr = [1, 3, 5];
        console.log(arr[Symbol.iterator]);
        let it = arr[Symbol.iterator]();
        console.log(it);
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
    
        for(let value of arr){
            console.log(value);
        }
      //对象没有实现,所以以下会报错
        // let obj = {
        //     name: "lnj",
        //     age: 34,
        //     gender: "man"
        // }
        // console.log(obj[Symbol.iterator]);
        // for(let value of obj){
        //     console.log(value);
        // }
        
      //以下我们自己实现Iterator,是的一个对象也可以通过for...of消费
        class MyArray{
            constructor(){
                for(let i = 0; i < arguments.length; i++){
                    // this[0] = 1;
                    // this[1] = 3;
                    // this[2] = 5;
                    this[i] = arguments[i];
                }
                this.length = arguments.length;
            }
            [Symbol.iterator](){//和以前在类里面写的函数格式不一样
                let index = 0;
                let that = this;
                return {
                    next(){
                        if(index < that.length){
                            return {value: that[index++], done: false}
                        }else{
                            return {value: that[index], done: true}
                        }
                    }
                }
            }
        }
        let arr = new MyArray(1, 3, 5);
        // console.log(arr);
        // console.log(arr[0]);
        // arr[0] = 666;
        // console.log(arr);
        for(let value of arr){
            console.log(value);
        }
        // console.log(arr[Symbol.iterator]);
        // let it = arr[Symbol.iterator]();
        // console.log(it);
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
    </script>
    
13.2 应用场景
  • <script>
        // 1.解构赋值
        class MyArray{
            constructor(){
                for(let i = 0; i < arguments.length; i++){
                    // this[0] = 1;
                    // this[1] = 3;
                    // this[2] = 5;
                    this[i] = arguments[i];
                }
                this.length = arguments.length;
            }
            [Symbol.iterator](){
                let index = 0;
                let that = this;
                return {
                    next(){
                        if(index < that.length){
                            return {value: that[index++], done: false}
                        }else{
                            return {value: that[index], done: true}
                        }
                    }
                }
            }
        }
        // let arr = [1, 3];
        let arr = new MyArray(1, 3);
        let [x, y, z] = arr;//将next中的value给x,y,没有就undefined
         console.log(x, y, z);
    
        // 2.扩展运算符
        // let arr1 = [1, 3];
        // let arr2 = [2, 4];
        let arr1 = new MyArray(1, 3);
        let arr2 = new MyArray(2, 4);
        let arr3 = [...arr1, ...arr2];
        console.log(arr3);
        
        //通过上面的例子,如果我们想要使用扩展运算符等,就可以自定义iterator接口来实现
    </script>
    

14 Generator函数

14.1 基本概念和使用
  • <script>
        /*
        1.什么是Generator函数?
        Generator 函数是 ES6 提供的一种异步编程解决方案
        Generator 函数内部可以封装多个状态, 因此又可以理解为是一个状态机
    
        2.如何定义Generator函数
        只需要在普通函数的function后面加上*即可
    
        3.Generator函数和普通函数区别
        3.1调用Generator函数后, 无论函数有没有返回值, 都会返回一个迭代器对象,
        3.2调用Generator函数后, 函数中封装的代码不会立即被执行
    
        4.真正让Generator具有价值的是yield关键字
        4.1在Generator函数内部使用yield关键字定义状态
        4.2并且yield关键字可以让 Generator内部的逻辑能够切割成多个部分。
        4.3通过调用迭代器对象的next方法执行一个部分代码,调用一次就执行第一部分的内容,两次就执行二部分
           执行哪个部分就会返回哪个部分定义的状态
    
        5.在调用next方法的时候可以传递一个参数, 这个参数会传递给上一个yield
        */
        function* gen() {
            console.log("123"); //1部分
            let res = yield "aaa";
    
            console.log(res);//2部分
            console.log("567");
            yield 1 + 1;
    
            console.log("789");//3部分
            yield true;
        }
        let it = gen();
        // console.log(it);
        console.log(it.next());
        console.log(it.next("it666"));//这个参数传给了上一个yield,会输出it666 567 以及这部分的状                                  态
        console.log(it.next());
        console.log(it.next());//没有这个状态,输出undefined
    
        // 注意点: yield关键字只能在Generator函数中使用, 不能在普通函数中使用
        // function say() {
        //     yield "abc";
        // }
        // say();
    </script
    
14.2 应用场景
  • <script>
        /*
        应用场景, 让函数返回多个值
        */
        /*
        function calculate(a, b) {
            let sum = a + b;
            let sub = a - b;
            return [sum, sub];
        }
        */
        function* calculate(a, b) {
            yield a + b;
            yield a - b;
        }
        let it = calculate(10, 5);
        console.log(it.next().value);
        console.log(it.next().value);
    </script>
    
  • <script>
        /*
        1. 应用场景: 利用 Generator 函数,可以在任意对象上快速部署 Iterator 接口
        */
        /*
        Generator 函数特点
        1.Generator 函数也是一个函数
        2.Generator 函数会返回一个迭代器对象
        3.迭代器对象有next方法
        4.next方法每次执行都会返回一个对象{value: xxx, done: false}
        */
        /*
        function* gen() {
            yield "aaa";
            yield "bbb";
            yield "ccc";
        }
        let it = gen();
        // console.log(it);
        console.log(it.next());
        */
    
        /*
       1.必须有一个叫做[Symbol.iterator]的属性
       2.[Symbol.iterator]的属性会返回一个函数
       3.[Symbol.iterator]返回的函数执行之后会返回一个可迭代对象
       4.[Symbol.iterator]函数返回的对象中又一个名称叫做next的方法
       5.next方法每次执行都会返回一个对象{value: xxx, done: false}
       */
        /*
        let obj = {
            name: "lnj",
            age: 34,
            gender: "man",
            [Symbol.iterator](){
                let keys = Object.keys(this);
                // console.log(keys);
                let index = 0;
                let that = this;
                return {
                    next(){
                        if(index < keys.length){
                            return {value: that[keys[index++]], done: false};
                        }else{
                            return {value: undefined, done: true};
                        }
                    }
                }
            }
        }
        // console.log(obj[Symbol.iterator]);返回函数
        // let it = obj[Symbol.iterator]();返回可迭代对象
        // console.log(it);
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        // console.log(it.next());
        for(let value of obj){
            console.log(value);
        }
        */
    
        let obj = {
            name: "lnj",
            age: 34,
            gender: "man"
        }
        function* gen(){
            let keys = Object.keys(obj);
            for(let i = 0; i < keys.length; i++){
                yield obj[keys[i]];
            }
        }
        obj[Symbol.iterator] = gen;
        // console.log(obj[Symbol.iterator]);
        let it = obj[Symbol.iterator]();
        // console.log(it);
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
    </script>
    
  • <script>
        /*
        应用场景: 用同步的流程来表示异步的操作
        */
        /*
        function request(fn) {
            setTimeout(function () {
                fn("拿到的数据");
            }, 1000);
        }
        request(function (data) {
            console.log("1", data);
            request(function (data) {
                console.log("2", data);
                request(function (data) {
                    console.log("3", data);
                });
            });
        });
        */
        function request() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    resolve("拿到的数据");
                }, 1000);
            });
        }
        /*
        request().then(function (data) {
            console.log(data, 1);
            return request();
        }).then(function (data) {
            console.log(data, 2);
            return request();
        }).then(function (data) {
            console.log(data, 3);
        });
        */
        function* gen() {
            yield request();
            yield request();
            yield request();
        }
        let it = gen();
        // console.log(it.next().value);//返回的promise对象放在value里面
        it.next().value.then(function (data) {
            console.log(data, 1);
            return it.next().value;
        }).then(function (data) {
            console.log(data, 2);
            return it.next().value;
        }).then(function (data) {
            console.log(data, 3);
        });
    </script>
    
14.3 async函数
  • <script>
        //我们上面通过Generator函数来用同步流程表示异步操作,但是看起来很麻烦,async函数就是来解决那个问      题的
        function request() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    resolve("拿到的数据");
                }, 1000);
            });
        }
        /*
        function* gen() {
            yield request();
            yield request();
            yield request();
        }
        let it = gen();
        it.next().value.then(function (data) {
            console.log(data, 1);
            return it.next().value;
        }).then(function (data) {
            console.log(data, 2);
            return it.next().value;
        }).then(function (data) {
            console.log(data, 3);
        });
        */
        async function gen() {
            let res1 = await request();
            console.log(res1, 1);
            let res2 = await request();
            console.log(res2, 2);
            let res3 = await request();
            console.log(res3, 3);
        }
        gen();
        /*
        1.async函数
        async函数是ES8中新增的一个函数, 用于定义一个异步函数
        async函数函数中的代码会自动从上至下的执行代码
    
        2.await操作符
        await操作符只能在异步函数 async function 中使用
        await表达式会暂停当前 async function 的执行,等待 Promise 处理完成。
        若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,然后继续执行 async function。
        * */
    </script>
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容

  • Promise 对象 Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函...
    neromous阅读 8,680评论 1 56
  • 在ES6当中添加了很多新的API其中很值得一提的当然少不了Promise,因为Promise的出现,很轻松的就给开...
    嘿_那个谁阅读 3,661评论 2 3
  • 一、Promise的含义 Promise在JavaScript语言中早有实现,ES6将其写进了语言标准,统一了用法...
    Alex灌汤猫阅读 815评论 0 2
  • # Ajax标签(空格分隔): 笔记整理---[TOC]### 从输入网址开始:- 在学习ajax之前,你应该先了...
    V8阅读 248评论 1 0
  • 前言 本文旨在简单讲解一下javascript中的Promise对象的概念,特性与简单的使用方法。并在文末会附上一...
    _暮雨清秋_阅读 2,174评论 0 3