zoukankan      html  css  js  c++  java
  • promise-async-await

      异步就是比较耗时的操作,CPU缓存的速度是最快的,然后是内存,然后是硬盘,所以从硬盘上读取文件是非常慢的,js认为从硬盘上读取文件是一个异步操作;另外一种是网络请求,这种也是异步的;操作dom节点也是非常耗时的,但却是同步操作,因为作为异步来处理比较麻烦。

      promise就是一个承诺,在js中就是承诺过段时间会返回一个结果,而这个过段时间就指的是异步操作。

      promise本质上是一个有限状态机,状态机指的是根据特定的条件按照一定的顺序进行转换,而且过程不可逆。每个promise实例都有三种状态:pending、resolve、reject。在状态机中,需要某些条件才能将自己的状态触发。

      状态只有两种:从初始状态到成功:pending->resolve;从初始状态到失败:pending->reject。promise实例状态机状态的变化会触发promise原型上的then或catch方法的执行

      DOM规范是运行在浏览器上的规范,比如navigator,只在dom上有,在node上没有;而ECMAScript规范,不仅在浏览器中可以使用,也可以在node.js中使用。

    如何构建一个promise

      构建一个promise实例需要给promise构造函数传入一个有两个形参的函数,第一个形参运行后会让promise实例处于resolve状态,所以一般用resove表示成功状态;第二个形参运行后会让promise实例处于reject状态,所以一般用reject表示失败状态。new出来的promise实例,有两个方法(then,catch,then捕获成功的操作,catch捕获失败的操作。),并且可以链式调用。在使用的时候,要将then放在catch的上面,这是因为then里的错误也可以在catch中捕获到,如代码所示:

    let promiseInstance = new Promise((resolve,reject) =>{
       setTimeOut(() => {
             resolve('this is resolve.')
       })
    })
    promiseInstance
    .then((value)=>{console.log(value)}).catch((err)=>{console.error(err)})

        promise是处理异步的,而网络请求是异步最常见的场景,所以可以用promise封装一个网络请求的方法,所以很多时候promise的实例是作为函数的返回值是,调用函数后可以对返回值的Promise对象进行相应的操作

    function ajaxPromise(){
      return new Promise((resolve,reject) => {
        let xhr = new XMLHttpRequest();
        xhr.open('get',queryUrl,true);
        xhr.send(null);
        xhr.onReadyStatechange = () => {
          if(xhr.readyState === 4){
            if(xhr.status === 200){
              resolve(xhr.responseText);
            }else{
              reject(xhr.responseText)
            }
          }
        }
      }) }

    ajaxPromise('http://api.github.com/')
    .then((value) => {
      console.log(value);
    })
    .catch((err) => {
      console.error(err)
    })

    then与catch的使用

      状态机的状态是不可逆的,所以执行了resolve方法,就算再执行reject方法,也不会有效果了。

    promise的api

      promise实例上的方法

        promise.prototype.then()

        promise.prototype.catch()

      promise构造函数上的方法

        promise.all(Array) 返回一个promise,等待参数中所有的promise都处于resolve状态后会触发返回的promise实例的resolve状态

        promise.race(Array) 返回一个promise,参数中第一个执行完成的状态决定出发哪个函数

        promise.resolve() 立刻返回一个resolve状态的实例

        promise.reject() 立刻返回一个reject状态的实例

    let promise1 = new Promise((resolve,reject)=>{
        setTimeout(resolve,1000,'success1')
    })
    let promise2 = new Promise((resolve,reject)=>{
        setTimeout(resolve,1000,'success12')
    })
    let promise3 = new Promise((resolve,reject)=>{
        setTimeout(resolve,1000,'success3')
    })
    Promise.all([promise1, promise2, promise3]).then((value)=>{
        console.log(value)
    }).catch((err)=>{
        console.error(err)
    })

    tips:setTimeOut的第三个参数,是第一个函数参数执行的时候,要传入的参数

    promise.then的执行时机

      promise.resolve是处理异步问题的,所以会先把同步的代码执行完,再执行promise.resolve返回实例的then或catch的代码

      而Promise构造函数是同步的,then方法是异步的。setTimeOut的执行时机是最晚的

    promise并不是处理异步最好的方法,比如回调金字塔的问题并没有解决,只是看起来更清晰了。解决异步最好的方法是async

    generator

      有点像一个函数内部有多个函数,是一个状态机,yield生成

    function* genFunc(){
      yield 'hello';
      yield 'generator';
      yield '!'
      return 'end'//generator不建议使用return
    }

     generator返回的不是返回值,也不是一个生成的内容,而是一个迭代器,迭代器是一个可遍历的对象,迭代器有个next方法。通过for-of循环遍历迭代器

    连续运行的generator

    function* genFunc(initValue){
      let first = yield new Promise((resolve,reject)=>{
        setTimeOut(resolve,1000,'1'+initValue)
      })
      let second = yield new Promise((resolve,reject)=>{
        setTimeOut(resolve,1000,'2-'+first)
      })
      let third = yield new Promise((resolve,reject)=>{
        setTimeOut(resolve,1000,'3-'+second)
      })
      let genHandler = genFunc(1)
      genHandler.next().value.
      then((value) => {
        genHandler.next(value).value.
        then((value) => {
          then((value) => {
            console.log(value);
          })
        })
      })
    } 

    co库与async函数

      import co from 'co'

      上述代码中依然有回调金字塔,可以用co库解决

    co(genFunc(1)).then((value) => {console.log(value)})//2-11

      async相当于是generator+promise+co,是es7的新语法,目前没有浏览器实现,所以需要用webpack+babel编译一下才可以运行。

    如何同步异步请求,即两次请求,异步执行,如何在两次请求都执行完成的情况下执行后续程序

    function request(content){
      setTimeout(()=>{
         document.body.append(content)
      },Math.floor(Math.random()*1000)) //时间控制为不确定
    }
    request('hello')
    request('world')
    //如何在两次request完成后执行代码。可以使用promise.all,只要两个异步有一个完成就可以,可以使用promise.race
    docuement.body.append('finished')

    如何处理回调嵌套回调

    //珠峰课堂是先去服务端拿取token,然后再去拿课程
    fetch('https://ketang.zhufengpeixun.cn/token')
    .then(response => {
        response.json().then(tokenJson =>{
             const token = tokenJson
             fetch('https:ketang.zhufengpeixun.cn/course')
             .then( response =>{
                response.json().then(tokenJson =>{
    
                }
             })
        })
    })

    promise定义:用于异步计算,代表一个当前、未来或永远不可用的值  

    //promise中的代码段被直接执行了
    const promise = new Promise((resolve,reject){
        document.body.append('hello')
    })
    const a = () =>{
        document.body.append('world')
    }
    a();
    
    //执行结果是hello world
    //用promise表示一个未来的值
    function resolve_example(){
      const promise = new Promise((resolve,reject)=>{
         document.body.append('start.....');
         setTimeout(()=>{//promise代表了一个未来值
            resolve('done')
         },2000)
      })
      return promise;
    }
    const promise = resolve_example();
    //得到一个未来完成的值,此处data是异步返回的部分
    promise.then(data => {
       document.body.append(data)
    })

     

    promise有三种状态,当被new出来的时候属于pending状态,使用resolve则是fulfill状态,使用reject则是fail状态

    Executor是构造Promise的唯一参数,在promise构造的时候会被马上执行

     

  • 相关阅读:
    sizeof运算符、虚函数、虚继承考点(待修改)
    sizeof运算符、字节对齐考点(面宝P50)
    浮点数的存储、类型转换知识点(面宝P34)
    赋值语句C++(面宝P29)
    求格子中的最短路径条数问题
    求两个数的最大公约数和最小公倍数Java(cvte考题)
    快速排序c代码
    希尔排序java代码
    快速排序java代码
    归并排序java代码
  • 原文地址:https://www.cnblogs.com/web-fengmin/p/6564066.html
Copyright © 2011-2022 走看看