美文网首页vue
半理解系列--Promise的进化史

半理解系列--Promise的进化史

作者: 小熊前端 | 来源:发表于2018-02-11 16:22 被阅读4次

半理解系列--Promise的进化史

学过js的都知道,程序有同步编程和异步编程之分,同步就好比流水线,一步一个脚印,做完上个任务才做下一个,异步编程好比客服,客服接了一个电话,收到了一个任务,然后把任务交给另外的人来处理,同时,继续接听下一个电话,等到另外的人处理完任务了,再通知客服,客服再反馈给第一个打电话的人。异步编程一般用来调取接口拉数据。

通过我描述的篇幅,就知道异步编程比同步编程麻烦许多。远古时期,异步编程是通过回调函数来解决的。但是回调函数会有回调地狱的问题,回调的多了,维护人员看起来头都大了,好比:taskC需要等待taskB做完(taskC才执行),taskB又需要等待taskA做完(taskB才执行)


function taskA (cb) {

  //..do task A

  cb()

}

function taskB(cb){

  //..do task B

  cb()

}

function taskC(cb){

  //..do task C

  cb()

}

taskA(function(){

  taskB(function(){

    taskC()

  })

})

...以此类推,不断循环嵌套,最终陷入地狱

而Promise就把这一系列的回调,通过链式调用的方式连接起来,看起来清爽多了。同样是上面的代码,Promise可以这么写(伪代码)


new Promise().then(taskA).then(taskB).then(taskC)

promise的使用


const promise = new Promise((resolve,reject)=>{

  if (/*do something done*/){

    resolve() // 可在此传参数

  } else {

    // do something fail

    reject() // 可在此传参数

  }

})

promise.then(()=>{

  //do something

}).catch(e => { throw e})

上面的resolve,可以当作task函数的cb回调函数,当resolve()执行的时候,then方法中的回调会被执行,如果是reject执行,错误会被catch捕捉。

Promise的静态方法

上面说的thencatch都是Promise的原型方法,即Promise.prototype.then/catch

Promise本身有两个静态方法,其作用类似 new Promise()

Promise.resolve()


const promise1 = Promise.resolve()

等价于

const promise2 = new Promise((reslove)=>{

  reslove()

})

使用该方法调用then方法

Promise.reject()


const promise1 = Promise.reject()

等价于

const promise2 = new Promise((resolve,reject)=>{

  reject()

})

使用该方法会被catch捕捉

Promise的链式调用

Promise的实例对象的then方法是可以重复调用的,then方法返回的是一个promise实例对象,所以可以重复调用then方法,并且(敲黑板),上一个then方法的返回值,会作为下一个then方法的参数传递

举个栗子:


const promise = Promise.resolve('start')

promise.then((params)=>{

  console.log(params) // start

  return 'aa'

}).then((params) => {

  console.log(params) // aa

  return 'bb'

}).then((params)=>{

  console.log(params) // bb

  return 'cc'

})

// 最后会返回一个状态是resolve(cc)的promise对象:Promise {: "cc"}

深入一下(又不会怀孕)


function badAsyncCall() {

  var promise = Promise.resolve();

  promise.then(function() {

      // 任意处理

      return 'newVar';

  });

  return promise;

}

// 修改一下

function goodAsyncCall() {

  var promise = Promise.resolve();

  return promise.then(function() {

      // 任意处理

      return 'newWar';

  });

}

以上两个写法是不是很相似,唯一不同的就是return的处理。但调用,badAsynccall会出错,而anAsyncCall能正确执行,比如:


badAsyncCall().then(params => { console.log('bad--',params)}) // bad-- undefined

goodAsyncCall().then(params => { console.log('good--',params)}) // good-- newWar

分析:第一种,错误写法,首先在 promise.then 中产生的异常不会被外部捕获,此外,也不能得到 then 的返回值,即使其有返回值。

原因:由于每次 promise.then 调用都会返回一个新创建的promise对象,第一种返回的promise,相当于没有调用过函数内部的then方法,是一个全新的promise实例对象

结论: 统一使用promise链式调用,如:promise.then(taskA).then(taskB)

### async&await和promise的前世缘缘

promise说白了还是用回调的方式来解决异步问题,跟真正同步还是有差距的。

异步编程的最高境界,就是根本不用关心它是不是异步!(来之ruanyifeng老师的话)

所以,async&await方案出现了

用法:


function readFile(fileName) {

  return new Promise((resolve,reject)=>{

    fs.readFile(fileName, function(error, data) {

      if (error) return reject(error);

      resolve(data); // 向thenc传送异步读取文件的数据

    });

  })

}

// 调用

readFile(fileName).then(function(data){

  console.log('prmoise read files data --', data)

})

// 等价于

async function asyncFn(fileName){

  const data = await readFile(fileName)

  console.log('await data --', data)

  return data

}

asyncFn(fileName)

写法是不是简洁了许多!

其实async就是一个Promise的语法糖,它的返回值是一个promise对象,因此可以用then方法做链式调用(但参数就是async函数中的返回值,如上文的data!!)

async函数中还可以不使用promise,比如:


async function asyncFn(){

  const data = await setTimeout(function(){

    console.log('setTimeout')

    return 'data'

  },1000)

  console.log('data',data) // Timeout {} 对象

}

console.log('async',asyncFn()) // Promise { }

但这两者,其实经常混用,常见的就是readFile函数的做法啦

看懂以上的,才大家出一道题看看能不能懂;


async function asynFn(){

  await Promise.resolve('aaa')

  const data = {

    b:'bb',

    c:function(){ return this.b }

  }

  return data  //return 作为参数传递给then then的chain链也是通过return参数来不断传递给后面的then

}

var cball = asynFn()

cball.then(function(data){

  console.log('data:',data)

})

还有一种异步编程的语法糖: * & yield

跟async基本一样,不在本文讨论的重点。有兴趣自行google啦

参考资料:

async 函数的含义和用法

Promise 对象

相关文章

网友评论

    本文标题:半理解系列--Promise的进化史

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