promise函数几种写法与坑

promise是ES6中引入的处理异步函数的强大特性,但是对promise的不恰当使用可能会达不到最终目的

对这个问题的探究来源于这篇文章关于promises,你理解了多少?

几个异步函数如下(resolve或reject在回调函数里被调用)

var func1 = function(last) {
  return new Promise((resolve, reject)=>{
    setTimeout(() => {
      console.log(`last:${last}`, 1);
      resolve(1);
    }, 100);
  });
};

var func2 = function(last) {
  return new Promise((resolve, reject)=>{
    setTimeout(() => {
      console.log(`last:${last}`, 2);
      resolve(2);
    }, 200);
  });
};

var func3 = function(last) {
  return new Promise((resolve, reject)=>{
    setTimeout(() => {
      console.log(`last:${last}`, 3);
      resolve(3);
    }, 300);
  });
};

下面几种不同写法会有什么区别?

Promise.resolve()
  .then((last)=>{return func1(last);})
  .then((last)=>{return func3(last);})
  .then((last)=>{return func2(last);});
Promise.resolve()
  .then((last)=>{func1(last);})
  .then((last)=>{func3(last);})
  .then((last)=>{func2(last);});
Promise.resolve()
  .then(func1(last))
  .then(func3(last))
  .then(func2(last));
func1(last)
  .then(func3(last))
  .then(func2(last));

运行结果

Promise.resolve()
  .then((last)=>{return func1(last);})
  .then((last)=>{return func3(last);})
  .then((last)=>{return func2(last);});

// last:undefined 1
// last:1 3
// last:3 2
Promise.resolve()
  .then((last)=>{func1(last);})
  .then((last)=>{func3(last);})
  .then((last)=>{func2(last);});

// last:undefined 1
// last:undefined 2
// last:undefined 3
Promise.resolve()
  .then(func1())
  .then(func3())
  .then(func2());

// last:undefined 1
// last:undefined 2
// last:undefined 3
func1()
  .then(func3())
  .then(func2());

// last:undefined 1
// last:undefined 2
// last:undefined 3
Promise.resolve()
  .then(func1)
  .then(func3)
  .then(func2);

// last:undefined 1
// last:1 3
// last:3 2

注意到,只有第一种和最后一种写法得到我们期望的结果,因此promise的正确用法,在每一个传入then的函数的最后,都要return一个promise对象,否则会导致函数仍然按自己的节奏异步执行
注意到最后一个样例,只是把第一个样例的(last)=>{return func1(last);}变成func1,两种写法是完全等价的,而后面的显得更简洁一点

当然,promise也允许我们return一个同步的值,例如

Promise.resolve()
  .then((last)=>{return func2(last);})
  .then((last)=>{return 3;})
  .then((last)=>{return func1(last);});

// last:undefined 2
// last:3 1

这意味着下一个then里面接收到的参数可以来自于同步,也可以来自于异步.其中执行的顺序,也不会改变

then期望得到的是一个接受若干个参数,返回一个promise或同步值的函数,如果不小心传入了一个promise,会有奇怪的结果(想法同样来自关于promises,你理解了多少?)

Promise.resolve('foo')
  .then(Promise.resolve('bar')) 
  .then((result)=>{console.log(result);}); //输出foo

Promise.resolve('foo')
  .then(Promise.resolve(1)) 
  .then((result)=>{console.log(result);}); //输出foo
  
Promise.resolve('foo')
  .then((result)=>{return Promise.resolve('bar');}) //输出bar
  .then((result)=>{console.log(result);});

第一个结果看起来应该是bar,但却出人意料地打印出了foo。出现这个结果的原因是第一个then得到的参数并不是一个函数对象,then会把所有非函数的输入值当作then(null)处理。因此净结果就是第一个Promise的返回值“穿透”到了最后一个then中。

因此这也是我们常说的一句话

永远都是往 then() 中传递函数!

Promise固然是ES6异步控制里最核心的组件之一,但实际应用中,我建议大家还是使用更容易阅读和使用的async/await语法糖。我们上面例子中的代码,使用async/await语法可以更清楚地写为:

f = async () => {
	let last = undefined
	last = await func1(last)
	last = await func3(last)
	last = await func2(last)
}
f()

// last:undefined 1
// last:1 3
// last:3 2

或不用async包装

let last = undefined
last = await func1(last)
last = await func3(last)
last = await func2(last)

// last:undefined 1
// last:1 3
// last:3 2
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值