简单理解Promise对象(JavaScript)

目录

一个引例:执行一个任务task

Promise的基本结构

Promise对象的链式调用

async异步函数同步化

Promise总结

 Promise是JavaScript的ES6标准新增功能,主要用来执行异步任务。

在JS中,所有代码都是单线程执行的。但是有很多事件,比如网络请求,必须是异步执行。

一个引例:执行一个任务task

//先定义2个函数
function resolve(s){
  console.log('成功:'+s);
};
function reject(s){
  console.log('失败:'+s);
};

//定义任务函数,需要2个参数,这2个参数也是函数
function task(resolve, reject) {
  //do task...
  //定时器,下面的内容2s后才执行
  setTimeout(()=>{
    if (true) {
      resolve('i am resolve');
    }
    else {
      reject('i am reject');
    }    
  },2000);
  console.log('任务完毕');
}

//执行任务
task(resolve,reject);

输出结果: 

任务完毕
成功:i am resolve

本例中,要执行任务函数task,需要2个参数:resolve,reject

resolve和reject这两个参数也是函数,通常是处理一下任务的返回结果。

任务执行后,如果任务成功了,我们让它执行resolve,如果失败了,我们让它执行reject。

本例中可以看到,task任务执行完毕了,然后才执行了resolve。

这样,任务函数task只管执行任务,不必理会任务执行完了要干什么;

resolve和reject函数只管处理任务的结果,不必理会任务是怎么执行的,什么时候结束的。

这个过程就类似网络请求的过程,网络请求只管去拿数据,但是要花一些时间,请求成功了一般就返回请求的数据,请求失败了就返回错误信息。那么只要成功了,就走resolve函数,并且把请求数据也传过去了(相当于 'i am resolve'),如果失败了,就走reject函数,也把错误信息传过去了(相当于 'i am reject')。

Promise的基本结构

new Promise(function).then(func1).catch(func2);

Promise是个类,需要传1个参数,参数就是它的构造函数(一般是异步函数),

这个异步函数又需要2个参数resolve、reject,这两个也都是函数,

其实这个Promise参数就是要执行的任务函数,在创建Promise对象时,会调用构造函数,开始执行任务。

new Promise(function(resolve, reject){
  //执行该任务...
  if(任务成功){
    resolve(res);//这个函数的定义就在then里面
  }
  else{
    reject(err);//这个函数的定义就在catch里面
  }
}).then(res=>{
  //任务成功,do something...
}).catch(err=>{
  //任务失败,do something...
});

promise对象有2个方法:then、catch

then方法的实参,就是resolve函数定义;执行then,就是执行resolve,参数res就是任务成功后的返回结果,通常就是请求的数据。
catch方法的实参,就是reject函数;执行catch,就是执行reject,参数err就是任务失败后的返回结果,通常就是错误信息。

现在,我们用Promise来改造前面的引例:

new Promise(function task(resolve, reject){
  //do task...
  setTimeout(()=>{
    if (true) {
      resolve('i am resolve');
    }
    else {
      reject('i am reject');
    }    
  },2000);
  console.log('任务完毕');
}).then(res=>{
  console.log('成功:'+res);//任务成功,走这里
}).catch(err=>{
  console.log('失败:'+err);//任务失败,走这里
});

注:

1. 任务函数通常是异步函数,需要一定时间。在上述例子中,使用setTimeout定时器的目的是模拟异步函数的执行时间,可以看到执行任务和处理结果是无关的。

2. 如果任务函数是同步函数(按顺序执行),那么使用Promise就没有意义了,直接使用普通函数去执行任务就行了。

Promise对象的链式调用

Promise的通用使用方式本身就是链式调用:

new Promise(function).then(func1).catch(func2);

其中,then和catch里面传递的都是函数。

then和catch里还可以传递其他的promise对象,当然,promise对象又有then和catch方法,又可以继续调用下去,形成链式调用。

//新的任务:累加,返回Promise对象
function add(n) {
  return new Promise(function (resolve, reject) {
    resolve(n + n);
  });
}

//把Promise对象封装到函数里
function grow(n){
  return new Promise(function (resolve, reject) {
    resolve(n);
  });
}

//连续执行任务
grow(2).then(add).then(add).then(add).then(res=>{
  console.log(res);
});

 以上代码输出结果:16

解读:

1.上述grow函数、add函数,都返回promise对象,把它封装成函数的目的是为了传参数。

2.grow函数的promise任务,返回2,传给了then;第1个add任务接收到2,返回4,传给了第2个add,第2个add返回8,传给第3个add,最后第3个add返回16,传给了最后的then,所以最终的计算结果是:16。

因此,我们可以向下面这样使用Promise链式调用:

job1.then(job2).then(job3).then(handleResult).catch(handleError);

注意:job1、job2、job3,都是Promise对象。

如果中间某个任务失败,会直接执行这个任务的catch,后面的任务不会执行了。

async异步函数同步化

Promise对象执行的任务都是异步函数,返回值通过then方法的res参数接收。

我们再看下面的例子:

定义一个异步函数grow,来执行异步任务add,add是promise对象。

//累加任务
function add(n) {
  return new Promise(function (resolve, reject) {
    resolve(n + n);
  });
}
//定义异步函数
async function grow(n){
  let res;
  res = await add(n);   //返回4
  res = await add(res); //返回8
  res = await add(res); //返回16
  console.log(res);
}

grow(2);//执行函数

以上代码输出结果:16

结果发现,给函数增加了 async、await 关键字,就可以直接获取promise对象返回的结果了,而不用使用then来接收结果。

上面函数的执行,看起来就好像是同步函数执行一样,这就是异步函数同步化处理。

注意:

1.必须增加 async、await 关键字;

2.异步函数同步化,其实代码逻辑只是看起来像普通的顺序执行逻辑,实际上每一步仍然需要等待成功返回,本质上仍然是异步的。

3.以上代码为了简化,缺少了reject失败的部分,添加reject部分后,只需要把执行任务的部分包在try...catch...里就可以了。

下面是调整后的代码:

//累加任务
function add(n) {
  return new Promise(function (resolve, reject) {
    if(true)
      resolve(n + n);
    else
      reject('error infomation.');
  });
}
//定义异步函数
async function grow(n, m){
  let res = n;
  try{
    for (let i=0; i<m; i++) {
      res = await add(res);
    }
    console.log(res);
  }
  catch(err){
    console.log(err);
  }
}
grow(2, 3);//执行函数,输出结果:16

Promise总结

1.使用promise对象的基本方式是:

new Promise(function).then(res=>{ ... }).catch(err=>{ ... });

任务function执行成功后的返回值res,执行失败后的返回值err;

任务成功后,就执行then,对res进行处理;

任务失败后,就执行catch,对err进行处理;

2.Promise对象可以链式调用:

job1.then(job2).then(job3).then(res=>{ ... }).catch(err=>{ ... });

job1、job2、job3...必须都是promise对象。

3.Promise异步同步化,必须使用async、await关键字。

可以直接获取promise任务成功的返回值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡十三刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值