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

半理解系列--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 {<resolved>: "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 { <pending> }

但这两者,其实经常混用,常见的就是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 对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值