IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> js学习之路(八) -> 正文阅读

[JavaScript知识库]js学习之路(八)

1. ajax

 /*
       ajax
         + 前后端交互的一种手段
         + 通过 JS 向服务端发起请求
           => 所有服务端返回的响应都不会直接显示再页面上
           => 而是返回给 js 这个语言
         + 说明: JS 和服务端交互
           => 依赖于浏览器来发送请求
         + ajax
           => a: async
           => j: javascript
           => a: and
           => x: xml
 
       使用方式
         1. 找到一个对象能帮我发送 ajax 请求
           => XMLHttpRequest() 内置构造函数
           => 专门创建实例化对象帮你发送 ajax 请求
 
         2. 对本次请求进行一些配置
           => open() 的方法
           => 语法: xhr.open(请求方式, 请求地址, 是否异步)
             -> 请求方式: GET POST PUT ...(大小写无所谓)
             -> 请求地址: 你要请求哪一个后端位置
             -> 是否异步: 选填, 默认是 true, 可以选填 false, 表示同步
 
         3. 把请求发出去
           => send() 方法
           => 语法: xhr.send()
 
         4. 接收响应
           => onload 事件
           => 语法: xhr.onload = function () {}
           => 本次请求结束以后触发(响应成功了以后触发)
           => xhr 里面有一个属性叫做 responseText 就是响应体
 
     */
 
     console.log('start')
 
     // 1. 创建一个 ajax 实例化对象
     const xhr = new XMLHttpRequest()
 
     // 2. 配置本次请求的信息
     xhr.open('GET', './server/get.php')
 
     // 3. 把这个请求发送出去
     xhr.send()
 
     // 4. 接收结果
     xhr.onload = function () {
       console.log(JSON.parse(xhr.responseText))
     }
 
     console.log('end')

2. ajax 的异步问题

 /*
      ajax 的异步问题

        1. open 的第三个参数可以配置
          => 默认是 true 表示异步
          => 可以选填 false 表示 同步

      分析四个步骤
        1. 创建 ajax 对象, 同步代码
        2. 配置请求信息, 同步代码
        3. 发送请求, 异步代码, 当代码执行到这句话的时候, 先把请求发出去
          => 等到响应的过程是异步
        4. 事件, 会在满足条件的时候触发
          => 条件: 响应回来

      异步执行的时候
        console.log('start')
        1. 创建 ajax 对象
        2. 配置请求信息
        3-1. 把请求发出去
        4. 绑定事件, 请求完成的事件
        console.log('end')
        3-2. 响应回到客户端, 触发事件
        console.log(响应体)

      同步执行的时候
        console.log('start')
        1. 创建 ajax 对象
        2. 配置请求信息
        3-1. 把请求发出去(同步), 等到响应回来再继续执行代码
        3-2. 响应回到客户端, 不会触发事件, 因为事件还没有绑定
        4. 绑定事件, 事件再也不会触发了
        console.log('end')
        + 如果想接收到响应, 需要再 send 之前绑定事件

      结论:
        + 同步的时候, 事件必须写在 send 之前
        + 异步的时候, 事件写在前面后面无所谓
        + 书写 ajax 的时候, 都要按照 1 2 4 3 的步骤写
    */

    console.log('start')

    // 1. 创建一个 ajax 实例化对象
    const xhr = new XMLHttpRequest()

    // 2. 配置本次请求的信息
    xhr.open('GET', './server/get.php', false)

    // 4. 接收结果
    xhr.onload = function () {
      console.log(JSON.parse(xhr.responseText))
    }

    // 3. 把这个请求发送出去
    xhr.send() // 发出去, 接收回来响应

    console.log('end')

3. ajax 的兼容

 /*
       ajax 的兼容
         + ajax 不动向下兼容
         + ajax 的兼容有两个部分
           1. 创建 ajax 对象
           2. 接收响应
 
       创建 ajax 对象的兼容
         1. new XMLHttpRequest()     标准浏览器使用
         2. new ActiveXObject('Msxml.XMLHTTP')     IE 7 8 9
         3. new ActiveXObject('Msxml2.XMLHTTP')    IE 6
         4. new ActiveXObject('Microsoft.XMLHTTP') IE 5.5+
         5. 再向下的 IE 不支持 ajax
         + 你用的 IE 11 浏览器, 跑不起来
           => ajax 是基于内核的兼容
 
       接收响应的兼容
         + 再 IE 低版本里面没有 onload 事件
         + 再 IE 低版本只能使用 onreadystatechange 事件来接收响应
           => 再事件里面进行判断
           => xhr.status 再 200 ~ 299 之间
           => xhr.readyState === 4 的时候
           => 正常使用响应体
     */
 
     var xhr = new XMLHttpRequest()
     console.log(xhr)
 
     xhr.open('GET', './server/get.php')
 
     xhr.onreadystatechange = function () {
       if (xhr.status >= 200 && xhr.status < 300 && xhr.readyState === 4) {
         console.log(xhr.responseText)
       }
     }
 
     xhr.send()
 
 
 
 
 
     /*
       ajax 状态码
         + 状态码
           => 响应状态码: 描述本次请求的状态
           => ajax状态码: 描述 ajax 进行到哪一个步骤了
         + 语法:  xhr.readyState
 
         0: 创建 ajax 对象成功
         1: 配置请求信息完成
         2: 请求发送出去了, 响应报文回到了浏览器
         3: 浏览器正在解析响应报文
         4: 浏览器解析响应报文成功, 已经可以正常使用 xhr.responseText
     */
 
 
     // const xhr = new XMLHttpRequest()
     // console.log(xhr.readyState)
 
     // xhr.open('GET', './server/get.php')
     // console.log(xhr.readyState)
 
 
     /*
       ajax 的状态码改变事件
         + xhr.onreadystatechange = function () {}
     */
 
     // 绑定一个状态码改变事件
     // xhr.onreadystatechange = function () {
     //   console.log(xhr.readyState)
     //   if (xhr.readyState === 2) {
     //     console.log('2 响应体 ' , xhr.responseText)
     //   }
 
     //   if (xhr.readyState === 3) {
     //     console.log('3 响应体 ' , xhr.responseText)
     //   }
 
     //   if (xhr.readyState === 4) {
     //     console.log('4 响应体 ', xhr.responseText)
     //   }
     // }
 
     // xhr.send()
 
 
     /*
       响应状态码
         + 再 xhr 里面还有一个信息表示 响应状态码
         + xhr.status
         + 描述本次请求的状态
     */
 
     // const xhr = new XMLHttpRequest()
     // xhr.open('GET', './server/get1.php')
     // xhr.onload = function () {
     //   console.log(xhr)
     // }
     // xhr.send()

4. 发送请求

/*
      发送一个带有参数的 get 请求
        + GET 请求就是直接再地址栏后面拼接 queryString 方式携带参数
        + open 的第二个参数就是请求地址
        + 我们把要携带给后端的内容通过 open 的第二个参数携带过去
    */

    const xhr = new XMLHttpRequest()

    xhr.open('GET', './server/get.php?a=100&b=200')

    xhr.onload = function () {
      console.log(JSON.parse(xhr.responseText))
    }

    xhr.send()
	
	 /*
	      发送一个带有参数的 post 请求
	        + POST 携带参数是在请求体, 不需要再地址栏拼接
	          => 数据格式无所谓, 但是要和 content-type 配套
	        + send() 的括号里面就是请求体
	        + 因为你没有设置 content-type 所以后端不能正常按照 $_POST 的方式解析
	          => 设置一下请求头, content-type 设置为 application/x-www-form-urlencoded
	          => 语法: xhr.setRequestHeader(key, value)
	    */
	
	    const xhr = new XMLHttpRequest()
	
	    xhr.open('POST', './server/post.php')
	
	    xhr.onload = function () {
	      console.log(JSON.parse(xhr.responseText))
	    }
	
	    // post 请求需要再请求之前设置请求头
	    xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
	
	    xhr.send('a=100&b=200')

5. 前后端交互的报错

 /*
      前后端交互的报错
        + JSON 解析出错了

      分析原因
        + 报错: JSON.parse(xxx) 出错了
        + xxx : 哪来的, 响应体, 后端给的
        + 百分百: 后端给的不是 json 格式的数据
        + 检查: 看后端给的到底是什么
          1. 把 JSON.parse 去掉, 直接打印 xhr.responseText
          2. 打开浏览器 -> network -> 找到你的这个请求 -> 点击 response
    */

    const xhr = new XMLHttpRequest()
    xhr.open('GET', './server/get.php?a=100&username=guoxiang')
    xhr.onload = function () {
      console.log(JSON.parse(xhr.responseText))
    }
    xhr.send()

6. 封装 ajax 操作

 /*
      封装 ajax 操作
        + 哪些作为参数使用
          => 请求方式
            -> type: 默认值 GET
          => 请求地址
            -> url: 必填
          => 是否异步
            -> async: 默认值 true
          => 是否执行 JSON.parse()
            -> dataType: 默认是 'string' 表示不解析, 'json'
          => 传递给后端的数据
            -> data: 'a=100&b=200' || { a: 100, b: 200 }

        + 确定一下传递参数的方式
          => function ajax() {}
          => ajax('./xxx.php', null, null, 'json', 'a=100')
          => ajax({ type: 'GET' })
          => 对象的方式传递参数

      开始封装
        1. 参数验证: 你传递的是不是符合规则
          1-1. url 验证, 必填
          1-2. type 验证, 可以不传递, 可以是 GET, 可以是 POST, 大小写无所谓
            => 其他的都不行
          1-3. async 验证, 可以不传递, 可以是 true 可以是 false
            => 要吗不传递, 要吗就是 boolean
          1-4. dataType 验证, 可以不传递, 要吗式 'string' 要吗式 'json'
          1-5. data 验证, 可以不传递, 可以是字符串类型, 可以是 object 类型
          1-6. success 和  error 验证, 可以不传递, 要吗就得式函数

        2. 设置一套默认值
          => 后期的请求发送都是使用默认值发送
          => 设置默认值的时候, 把 data 单独操作一下
          => 判断如果是一个对象, 我把他还原成 字符串的形式再使用

        3. 发送请求
          => 按照 _default 里面的内容发送请求

        4. 回调函数
          => 目前发送 ajax 只能把结果再控制台打印
          => 我们就把想在请求结束后做的事情包装成一个 盒子, 传递给 ajax 里面
          => 让他再请求成功的时候, 给我把盒子执行掉
    */

    ajax({
      url: './server/get1.php',
      data: { a:100, b:200 },
      dataType: 'json',
      success: function (xhr) {
        console.log('请求成功')
        console.log('我想渲染页面, 根据结果判断登录是否成功')
        console.log(xhr)
      },
      error: function (err) {
        console.log('请求失败')
        console.log(err)
      }
    })

    function ajax(options = {}) {
      // options = {} 目的: 为了保证你的 options 是一个对象
      // 我执行 options.xxx 的时候不会报错
      // options.success 和 error 式两个函数数据类型或者没传递

      // 1. 参数验证
      // 1-1. 验证 url
      if (!options.url) {
        throw new Error('url 为必填选项')
      }

      // 1-2. 验证 type
      if (!(options.type == undefined || options.type.toUpperCase() === 'GET' || options.type.toUpperCase() === 'POST')) {
        throw new Error('目前只接收 GET 或者 POST 请求方式, 请期待更新')
      }

      // 1-3. 验证 async
      if (!(options.async == undefined || typeof options.async === 'boolean')) {
        throw new Error('async 需要一个 Boolean 数据类型')
      }

      // 1-4. 验证 dataType
      if (!(options.dataType == undefined || options.dataType === 'string' || options.dataType === 'json')) {
        throw new Error('目前只支持 string 和 json 格式解析, 请期待更新')
      }

      // 1-5. 验证 data
      if (!(options.data == undefined || typeof options.data === 'string' || Object.prototype.toString.call(options.data) === '[object Object]')) {
        throw new Error('data 参数只支持 string 和 object 数据类型')
      }

      // 1-6. 验证 success 和 error
      if (!(options.success == undefined || typeof options.success === 'function')) {
        throw new Error('success 传递一个函数类型')
      }

      if (!(options.error == undefined || typeof options.error === 'function')) {
        throw new Error('error 传递一个函数类型')
      }

      // 代码来到这里, 说明 options.success 和 error 肯定是一个 undefined 或者 function

      // 2. 设置一套默认值
      var _default = {
        url: options.url,
        // 代码能来到这里, 说名 undefined  get  post
        type: options.type || 'GET',
        // 代码能来到这里, 说明 undefined true false
        // 三元表达式, 如果你式个 布尔值, 那么就用你的, 否则用 true
        async: typeof options.async === 'boolean' ? options.async : true,
        // 代码能来到这里, 说明 undefined 'string' 'json'
        dataType: options.dataType || 'string',
        // 代码能来到这里, 说明 undefined '' {}
        data: options.data || '',
        // 如果你传递了是一个 function, 就用你传递的, 否则我就给一个默认函数
        success: options.success || function () {},
        error: options.error || function () {}
      }

      // 到这里, _default.success 和 error 肯定式一个函数

      // 2-2. 单独调整一下 data
      // 能来到这里, _default.data 只能是 '' {}
      if (typeof _default.data === 'object') {
        // 准备一个空字符串
        var str = ''
        for (var key in _default.data) {
          str += key + '=' + _default.data[key] + '&'
        }
        // 拼接完毕以后, 把最后一位去掉, 从新赋值给 _default.data
        _default.data = str.slice(0, -1)
      }


      // 3. 发送请求
      var xhr = creXhr()

      // 3-1. 请求地址, 如果是 get 请求 url + '?' + data
      //               如果式 post 请求 url
      // 判断, 如果是 get 请求, 那么我把 _default.url 修改一下
      if (_default.type.toUpperCase() === 'GET' && _default.data) {
        _default.url += '?' + _default.data
      }
      xhr.open(_default.type, _default.url, _default.async)
      xhr.onreadystatechange = function () {
        if (xhr.status >= 200 && xhr.status < 300 && xhr.readyState === 4) {
          // 3-3. 判断 dataType 如果式 json 要解析
          if (_default.dataType === 'json') {
            // 成功, 不需要打印
            // 调用 _default.success()
            var res = JSON.parse(xhr.responseText)
            // 要吗调用的式你传递进来的函数, 要吗调用的式默认函数
            // 调用的如果式默认函数, 那么就相当于什么都没执行
            // 如果调用的式你传递进来的函数, 那么你在函数里面写什么就执行什么
            _default.success(res)
          } else if (_default.dataType === 'string') {
            _default.success(xhr.responseText)
          }
        }

        if (xhr.readyState === 4 && xhr.status >= 400) {
          _default.error(xhr.status)
        }
      }

      // 3-2. 判断是不是 post 请求
      if (_default.type.toUpperCase() === 'POST') {
        xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
      }
      xhr.send(_default.data)
    }



  </script>





  <script>
    /*
      封装 ajax

      设计模式: 为了解决特定问题而给出的简洁优化的解决方案
        + 懒惰模式: 多种方案选择一种的方式
        + 例子: 创建 ajax 对象
          => 四种方式
          => 封装的时候要判断
          => 假设: 刚好是第四个可以用
          => 再找个页面你创建两次的时候,
            -> 第一次要判断到第四个
            -> 第二次还是要判断到第四个
        + 懒惰模式, 第一次的时候, 判断到第四个, 从第二次开始, 不再进行判断

      1. 封装创建 xhr 对象
      2. 封装 ajax
    */


    /*
      封装一个函数, 创建 xhr 对象
        => 不需要参数
        => 返回值就是一个可以再本浏览器使用的 xhr 对象

      封装过程

        1. 把每一种创建方式写成一个函数
          => 依次去调用找个函数
          => 如果不报错, 表示这个方法可以使用
          => 如果 a 函数可以使用, 表示 a 函数里面的代码再当前浏览器可以正常创建
          => 我把 creXhr 重新赋值, 赋值为 a
          => 从此以后, 当你再次调用 creXhr 的时候, 其实就是再调用 a 函数

        2. 把四个函数放在一个数组里面
          => 循环遍历这个数组
          => 循环的尝试

        3. 准备一个开关
          => 判断数组里面是不是有能执行的
          => 开始的时候式 false
          => 一旦有一个可以使用 变量赋值为 true
    */

    // function creXhr() {
    //   var xhr = null

    //   // 准备一个变量
    //   var flag = false

    //   // 根据各种判断, 来给 xhr 赋值
    //   var arr = [
    //     function a() { return new XMLHttpRequest() },
    //     function b() { return new ActiveXObject('Microsoft.XMLHTTP') },
    //     function c() { return new ActiveXObject('Msxml.XMLHTTP') },
    //     function d() { return new ActiveXObject('Msxml2.XMLHTTP') }
    //   ]

    //   for (let i = 0; i < arr.length; i++) {
    //     // arr[i] 式里面的每一个函数
    //     try {
    //       xhr = arr[i]()
    //       // 这里的代码可以执行, 表示 arr[i] 函数里面写的代码就是当前浏览器用的
    //       creXhr = arr[i]
    //       flag = true
    //       break
    //     } catch (e) {}
    //   }

    //   // 判断 flag
    //   // 如果式 false, 表示数组里面的每一个都不能用
    //   if (!flag) {
    //     xhr = '您的浏览器不支持 ajax, 请更换浏览器重试'
    //     throw new Error(xhr)
    //   }

    //   // 返回 xhr
    //   return xhr
    // }

7. 跨域

/*
      同源策略
        + **同源策略是浏览器给的一个行为**
        + 当你再发送请求的时候, 会涉及到两个地址
          1. 打开当前页面的地址
          2. 你要请求的地址
        + 两个地址中的 端口号 域名 传输协议
          => 只要由任意一个不一样, 就是非同源请求
          => 就会触发浏览器的同源策略
          => 不允许你获取这个服务器上的数据

      触发了同源策略的请求我们叫做 跨域请求
        + 私人: 请求别人家的服务器
        + 第一:
          => 真实开发环境
          => 页面(html, js, css, 静态资源) 是在一个服务器上
          => 所有的数据, 数据库, 在一个服务上
        + 第二:
          => 真实开发环境
          => 我自己不具备条件, 购买别人家服务器服务
          => 美团: 地图功能
          => 新闻: 买新浪的接口, 腾讯的接口

      解决浏览器不允许请求别人家服务器的情况
        + 基于 http 协议
        1. jsonp
        2. cors
        3. 代理
    */

    /*
      打开页面 http://localhost:80/04_跨域请求.html
      请求地址 http://localhost:80/server/test.php
    */
    // ajax({
    //   url: './server/test.php',
    //   success (res) {
    //     console.log(res)
    //   }
    // })

    /*
      打开页面 http://localhost:80/04_跨域请求.html
      请求地址 http://127.0.0.1:80/server/test.php
    */
    // ajax({
    //   url: 'http://127.0.0.1:80/server/test.php',
    //   success (res) {
    //     console.log(res)
    //   }
    // })


    /*
      地址
        + 打开页面 localhost/index.html
          => 再页面里面发送一个请求 ajax({ url: './a.php' })
          => 请求地址: localhost/a.php
        + 完整地址
          => 打开页面 http://localhost:80/index.html
          => 请求地址 http://localhost:80/a.php
    */

8. jsonp 跨域

  /*
       jsonp 跨域
         + 因为浏览器的同源策略, 不允许发送跨域的 ajax 请求
         + 我们使用 jsonp 手法来实现跨域请求
 
       script 标签
         + script 标签可以执行 js 代码
           => script 标签有一个属性叫做 type="text/javascript"
           => 就会把里面的代码当作 js 来解析
           => 当你不写 type 属性的时候, 默认是 text/javascript
         + src 属性
           => src 是引入外部资源的属性
           => 不受同源策略的影响
         + 当上面两个加再一起
           => 只要你引入任何一个内容, 都会被当作 js 代码来解析
 
       jsonp 的核心
         + 利用 script 标签的 src 属性
         + 去向一个非同源的服务器请求数据
         + 只要这个服务器能给我返回一个字符串
         + 我就会把这个字符串当作 js 代码来执行
 
       jsonp 请求数据
         + 要求服务器返回一个 函数名() 这样的字符串
         + 要求提前准备号一个函数
         + 要求前端告诉后端你准备好的函数名是什么
           => 再发送请求的时候, 以参数的形式告诉后端
           => 我准备好的函数名叫做什么
 
       jsonp 常见的面试题
         1. jsonp 原理
           => src 不受同源策略影响
           => script 标签会把请求的内容当作 js 代码来执行
         2. jsonp 的返回值
           => 字符串, 函数名() 形式的字符串
           => 一段可以执行的 js 代码字符串
         3. jsonp 的优缺点
           => 优点
             -> 绕开了同源策略, 实现跨域请求
             -> 方便, 因为是以 script 标签外部资源的形式请求
           => 缺点
             -> 不好做安全防范
     */

9.跨域请求

 /*
      跨域请求
        + 什么是同源策略
          => **同源策略是浏览器给的机制**
          => 当你再发送一个请求的时候
          => 打开页面的地址和请求地址中, 端口号 传输协议 域名, 有任意一个不一样
          => 就是触发了同源策略
          => 浏览器不允许你请求这个服务器的数据
        + 什么是跨域请求
          => 当触发了同源策略以后, 我还需要获取该服务器的数据
          => 这种请求叫做跨域请求
        + 跨域请求的解决方案
          => 基于 http 协议的跨域方案
          1. jsonp
            -> 利用了 src 属性不受同源策略的影响
            -> 利用了 script 标签会把请求回来的内容当作 js 代码来执行
            -> 要求服务器返回一段可以执行的 js 代码( 函数名(数据) )
            -> 要求前端提前准备好这个被执行的函数
            -> 要求前端以参数的形式把这个被执行函数的函数名传递到后端
          2. 代理
            -> 利用一个正向代理的机制来实现
            -> 任何一台服务器都可以做代理
              => apache 服务器 代理 http 协议的是免费的
              => apache 服务器 代理 https 协议需要证书的
              => 我们配置代理使用 nginx 服务器来配置代理
            -> 配置
              => phpstudy 切换到 nginx 服务器
              => 其他选项菜单 -> 打开配置文件 -> nginx.conf
              => 找到当前服务器的 server 标签对, 找到闭合标签的上一行书写代理配置
              => location = /xx {
                proxy_pass 地址;
              }
                -> /xx: 代理标识符, 当你请求 /xx 的时候, nginx 会发现你在请求代理标识符
                        就会自动帮你转发你的请求到 proxy_pass 后面的地址
                -> proxy_pass: 代理目标地址
              => 只要配置文件被修改了, 那么就要重启服务器
          3. cors - 跨域资源共享
            => 因为跨域请求, 不是请求发不出来
            => 实际上: 请求已经发送了, 而且到了服务器了, 响应页回到浏览器了
            => 但是浏览器判断了是非同源位置, 不允许你使用服务器给回的数据
            => 由服务器告诉浏览器一个事情, 这个域名我允许请求我的内容
            header("Access-Control-Allow-Origin:*");
            header("Access-Control-Request-Methods:GET, POST");
            header('Access-Control-Allow-Headers:x-requested-with,content-type,test-token,test-sessid');
    */

10.函数防抖

/*
      函数防抖
        + 在一个时间节点内, 多次触发同一事件
        + 不需要每一次都执行, 只需要在一个固定时间内, 没有重复操作的时候
        + 执行一次事件
        + 例子: 滚动条事件
          -> 在我一直快速滚动的时候, 你不要触发
          -> 等到我的滚动结束了, 停下来以后你在触发
        + 实现:
          -> 准备一个定时器, 把你要做的事情放在定时器里面做
          -> 当你在 300 ms 内做同一个行为的时候, 把定时器关闭掉
          -> 只有当你停下来的一瞬间, 不会再继续关闭定时器的时候, 才会触发事件
    */

    var timer = null

    window.onscroll = function () {
      clearInterval(timer)

      timer = setTimeout(() => {
        console.log('触发')
      }, 300)
    }


    /*
      不停的触发滚动事件
        1. 关闭定时器, 没得关代码白执行
           timer 赋值为 300 ms 以后执行
        2. 300ms 以内当我触发第二次的时候
           关闭之前的哪个定时器, 之前那一次 300ms 以后的就不会执行了
           从新设置了一个 300ms 的定时器
    */

11.函数节流

 /*
       函数节流
         + 再固定时间内, 重复触发同一事件
         + 我们再固定时间内, 只有第一次时候执行, 后面的每一次都不再执行了
         + 知道我们设定的固定时间到达以后, 再次允许执行下一个事件
         + 例子: 滚动
           => 随着滚动一直触发事件
           => 只要你添加一个定时器就可以了
             -> 定时器的作用, 只是为了模拟一个多少时间以后
           => 准备一个开关, 事件里面的代码根据开关来决定是不是执行
     */
 
     // 做一个开关
     var flag = true
 
     window.onscroll = function () {
       if (flag === false) return
 
       // 能来到这里, 说明 flag 是 true
       flag = false
 
       console.log('我执行了')
       setTimeout(() => {
         // 再次把开关打开
         flag = true
       }, 300)
 
     }
 
     /*
       随着滚动一直再触发 scroll 事件
       1. flag === true,  关闭开关, 执行要执行的代码, 设置定时器
       2. 300ms 以内, 再次触发事件的时候, flag === false
       3. 300ms 以内, 再次触发事件的时候, flag === false
       4. 300ms 以后, 开关变成开启, 再次执行事件, flag === true, 执行要执行的代码, 设置定时器
     */

12.回调函数 callback

  /*
       回调函数 callback
         + 什么是回调函数
           => 定义: 把 A 函数当作参数传递到 B 函数内部
                    再 B 函数内部以形参的方式调用 A 函数
           => 这种函数的调用方式, 我们叫做回调函数(callback)
         + 回调函数的缺点:
           => 回调地狱
           => 不停的再一个回调函数里面去进行第二个回调函数的操作
           => 就是代码没有可读性和可维护性
         + 为什么需要回调函数
           => 异步
           => 因为我要在异步的末尾或者中间做一些事情
     */
 
     /*
       需求1:
         发送请求: 请求 a.php 文件
         能返回两个结果, 一个a 一个 b
       需求2:
         发送请求: 请求 b.php 文件
         需要携带参数: 第一个 a.php 文件返回的两个数字
       需求3:
         发送请求: 请求 c.php 文件
         需要携带参数: 第一个 b.php 文件返回的两个数字
     */
 
     let obj = null
 
     // 多出现在开发中
     ajax({
       url: './server/a.php',
       dataType: 'json',
       success (res) {
         console.log('需求1: ', res)
         ajax({
           url: './server/b.php',
           data: res,
           dataType: 'json',
           success (res) {
             console.log('需求2: ', res)
             ajax({
               url: './server/c.php',
               data: res,
               dataType: 'json',
               success (res) {
                 console.log('需求3: ', res)
               }
             })
           }
         })
       }
     })
 
 
 
 
 
     // 多出现再面试题
     // (function (cb) {
     //   console.log('b')
     //   cb(function (cb) {
     //     console.log('c')
     //     cb(new Date())
     //   })
     // })(function (cb) {
     //   console.log('a')
     //   cb(function (res) {
     //     console.log(res)
     //   })
     // })

13.Promise

 /*
      Promise - 承诺
        + 一个承诺多少个状态
          => 持续  pending
          => 成功  resolved
          => 失败  rejected
        + ES6 的语法
          => 专门用来解决回调地狱问题

      Promise 的语法
        + Promise 是 ES6 内置的构造函数
        + 语法: new Promise(function () { 你要执行的异步的事情 })
          => 实例化的时候, 这个函数接收两个参数
          => resolve, reject
        + 语法:
          => 实例化对象身上由两个方法
          1. then()
            -> promise对象.then(function () {})
          2. catch()
            -> promise对象.catch(function () {})
          => then 方法的函数传递给了 实例化的 resolve
          => catch 方法的函数传递给了 实例化的 reject


      Promise 的进阶语法
        + 当你再一个 promise 对象的 then 里面返回一个新的 promise 对象
        + 你可以再这个 then 的后面继续来一个 then 接收第一个 then 里面 promise 对象的结果

      改变封装异步代码的思路
        + 按照 promise 的思想来封装异步代码
        + 分析: 为什么可以使用 then
          => 得是一个 promise 对象
        + 封装:
          => function pAjax() {}
          => 只要 pAjax 里面返回的是一个 promise 对象
          => pAjax({ 配置项 }).then()

      Promise 的另一种语法
        + Promise.all()
        + 目的是把多个 promise 对象封装成一个
        + 语法: Promise.all([ promise对象1, promise对象2, ... ]).then(function () {})
        + then 里面会接收所有 promise 完成以后的结果, 以一个数组的形式给你返回
        + 致命缺点: 必须三个全部成功, 由任何一个失败, 那么最终你一个结果也得不到
    */


    // const p1 = new Promise((resolve, reject) => {
    //   setTimeout(() => {
    //     resolve('结果 1')
    //   }, Math.random() * 5 * 1000)
    // })

    // const p2 = new Promise((resolve, reject) => {
    //   setTimeout(() => {
    //     // resolve('结果 2')
    //     reject('结果 2 失败')
    //   }, Math.random() * 5 * 1000)
    // })

    // const p3 = new Promise((resolve, reject) => {
    //   setTimeout(() => {
    //     resolve('结果 3')
    //   }, Math.random() * 5 * 1000)
    // })

    // 使用 all() 把他们合成一个
    // Promise
    //   .all([ p1, p2, p3 ])
    //   .then(res => {
    //     console.log(res)
    //   })
    //   .catch(err => {
    //     console.log(err)
    //   })




    // pAjax({
    //   url: './server/a.php',
    //   dataType: 'json'
    // })
    // .then(res => {
    //   console.log('需求1: ', res)
    //   return pAjax({
    //     url: './server/b.php',
    //     data: res,
    //     dataType: 'json'
    //   })
    // })
    // .then(res => {
    //   console.log('需求2: ', res)
    //   return pAjax({
    //     url: './server/c.php',
    //     data: res,
    //     dataType: 'json'
    //   })
    // })
    // .then(res => {
    //   console.log('需求3: ', res)
    // })



    // 2. Promise 进阶语法
    // new Promise(function (resolve, reject) {
    //   ajax({
    //     url: './server/a.php',
    //     dataType: 'json',
    //     success (res) {
    //       resolve(res)
    //     }
    //   })
    // })
    // .then(function (res) {
    //   console.log('需求1: ', res)
    //   return new Promise(function (resolve, reject) {
    //     ajax({
    //       url: './server/b.php',
    //       data: res,
    //       dataType: 'json',
    //       success (res) {
    //         resolve(res)
    //       }
    //     })
    //   })
    // })
    // .then(function (res) {
    //   console.log('需求2: ', res)
    //   return new Promise(function (resolve, reject) {
    //     ajax({
    //       url: './server/c.php',
    //       data: res,
    //       dataType: 'json',
    //       success (res) {
    //         resolve(res)
    //       }
    //     })
    //   })
    // })
    // .then(function (res) {
    //   console.log('需求3: ', res)
    // })





    // then 传递的这个 function a返回什么, then 的返回值就是什么
    // a 函数的返回值, 就是 then 的返回值
    // const p2 = p.then(function a(res) {
    //   console.log('需求1: ', res)

    //   // 这里就是一个 promise 的 then, 再这里返回一个新的 promise 对象
    //   const result = new Promise(function (resolve, reject) {
    //     ajax({
    //       url: './server/b.php',
    //       data: res,
    //       dataType: 'json',
    //       success (res) {
    //         resolve(res)
    //       }
    //     })
    //   })

    //   // result 是一个新的 promise 实例化对象
    //   // return 以后, p2 得到的就是这个 result 新的 promise 实例化对象
    //   return result
    // })


    // p2.then(function (res) {
    //   console.log('需求2: ', res)
    // })





    // 1. promise 基础语法
    // const p = new Promise(function (resolve, reject) {
    //   // resolve 是成功的回调函数
    //   // 当你书写 resolve() 的时候, 实际上是在调用 then 里面的函数
    //   // reject 是失败的回调函数
    //   // 当你书写 reject() 的时候, 实际上是在调用 catch 里面的函数
    //   ajax({
    //     url: './server/a1.php',
    //     dataType: 'json',
    //     success (res) {
    //       resolve(res)
    //     },
    //     error (err) {
    //       reject(err)
    //     }
    //   })
    // })
    // 调用 then 方法
    // 调用 catch 方法
    // p.then(function (res) {
    //   console.log('我执行了', res)
    // })
    // p.catch(function (err) {
    //   console.log('我失败了', err)
    // })

14. async / await

 /*
      async / await
        + ES7 的语法
          => ES6 提出的方案, 但是 ES6 实现的不是很好
          => 再 ES7 的时候优化过
        + 目的:
          1. 回调地狱的终极解决办法
          2. 把异步代码写的看起来像同步代码

      语法:
        1. async 书写再函数的前面, 是对这个函数的修饰关键字
        2. await 的使用, 必须有 async 关键字, await 才可以再函数内部使用
        3. await 等待的必须是一个 promise 对象, 才会有等待的结果, 不然没有意义
        + 当你满足了以上三个条件以后, 你的 promise 对象本该再 then 里面接收的结果
          => 就可以直接定义变量接收
          => 你的 promise 里面的异步代码没有结束之前
          => 不会继续向下执行
    */

    // fn 是一个异步函数
    // async function fn() {
    //   // await 关键字, 这个函数必须要有 async
    //   const res = await pAjax({ url: './server/a.php', dataType: 'json' })
    //   // 当 pAjax 发送的请求没有回来之前, res 不会被赋值
    //   // 只有请求回来以后, res 才会被赋值

    //   // 如果这段打印先于请求回来执行, res 没有结果
    //   // 如果 res 有结果, 证明: 这段代码被延后执行了, 延后到后面的 promise 对象完成以后
    //   console.log(res)
    //   console.log('后续代码')
    // }

    // fn()


    // async function fn() {
    //   const res1 = await pAjax({ url: './server/a.php', dataType: 'json' })
    //   console.log('需求1: ', res1)

    //   const res2 = await pAjax({ url: './server/b.php', dataType: 'json', data: res1 })
    //   console.log('需求2: ', res2)

    //   const res3 = await pAjax({ url: './server/c.php', dataType: 'json', data: res2 })
    //   console.log('需求3: ', res3)
    // }

    // console.log('start')
    // fn()
    // console.log('end')

    const div = document.querySelector('div')
    div.addEventListener('click', async () => {
      const res1 = await pAjax({ url: './server/a.php', dataType: 'json' })
      console.log('需求1: ', res1)

      const res2 = await pAjax({ url: './server/b.php', dataType: 'json', data: res1 })
      console.log('需求2: ', res2)

      const res3 = await pAjax({ url: './server/c.php', dataType: 'json', data: res2 })
      console.log('需求3: ', res3)
    })

15. generator 函数

 /*
      generator 函数
        + 一种长得很像函数的玩意
        + 但是不是函数, 函数生成器(迭代器)

      语法:
        + 再定义函数的时候,  再 function 后面 或者 函数名前面加一个 星号(*)
        + 函数内部可以使用一个 yield 关键字
          => 类似于 return 一样的作用
          => 可以给你制造一个结果
          => 让这个 generator 暂停
          => 当你再次回到这个 generator 的时候, 从上次 yield 继续向后执行代码
        + generator 的返回值是一个迭代器
          => 包含一个 next() 方法
          => 每一次 next 执行, 就会执行到下一个 yield 位置为止
    */

    // 当有了星号以后, fn 不再是一个函数了
    function* fn() {
      console.log('我是第一段 代码')

      yield '第一段结束'

      console.log('我是第二段 代码')

      yield '第二段结束'

      console.log('我是第三段 代码')

      return '第三段结束'
    }

    // result 就是 fn 给生成一个 迭代器
    const result = fn()

    // 第一次, 从 fn 的开头执行到第一个 yield,
    // 把 yield 后面的东西当作返回值
    const first = result.next()
    console.log(first)

    // 第二次, 从第一次的 yield 后面开始执行到第二个 yield 结束
    // 把 第二个 yield 后面的东西当作返回值
    const second = result.next()
    console.log(second)

    const third = result.next()
    console.log(third)
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:20:01  更:2022-03-08 22:24:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:37:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码