美文网首页
js新特性之网络编程0808

js新特性之网络编程0808

作者: 煤球快到碗里来 | 来源:发表于2019-08-08 23:01 被阅读0次

    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>
      

    相关文章

      网友评论

          本文标题:js新特性之网络编程0808

          本文链接:https://www.haomeiwen.com/subject/vxrqjctx.html