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构造的时候会被马上执行

 

posted @ 2017-04-18 14:51  叮呤  阅读(358)  评论(0编辑  收藏  举报