技术问询:四种JavaScript ES6 Promise写法有何区别?
四种ES6 Promise写法的核心区别
嘿,这几个写法乍一看差不多,但实际运行逻辑和Promise链的行为差异很大,咱们逐个拆解明白:
1. doSomething().then(function () { return doSomethingElse(); });
这个写法里,doSomething完成(状态变为resolved)后,会执行匿名回调函数:
- 回调里调用
doSomethingElse(),并返回它的Promise实例 - 因此,这个
then会等待doSomethingElse的Promise完成,才会推进到下一个链式调用(如果有的话) - 注意:如果
doSomething有返回值,这个匿名函数没接收参数的话,doSomethingElse拿不到这个值——比如如果doSomethingElse需要依赖doSomething的结果,得写成function(result) { return doSomethingElse(result); }
举个实际运行的例子:
function doSomething() { return new Promise(resolve => setTimeout(() => resolve('doSomething done'), 1000)); } function doSomethingElse() { return new Promise(resolve => setTimeout(() => resolve('doSomethingElse done'), 1000)); } doSomething() .then(() => { return doSomethingElse(); }) .then(result => console.log(result)); // 会在2秒后输出"doSomethingElse done"
2. doSomething().then(function () { doSomethingElse(); });
和第一个写法的核心区别是没有返回doSomethingElse()的Promise:
doSomething完成后执行匿名回调,调用doSomethingElse()但不返回任何值(默认返回undefined)- Promise规则里,
then的回调如果返回非Promise值,会被包装成一个立即resolved的Promise(值为undefined) - 所以下一个链式调用会立刻执行,完全不等
doSomethingElse的异步操作完成 - 这是常见的bug点——如果你想等待
doSomethingElse,却忘了return它的Promise
例子:
doSomething() .then(() => { doSomethingElse(); }) .then(result => console.log(result)); // 1秒后输出undefined,而doSomethingElse还在后台运行
3. doSomething().then(doSomethingElse());
这个写法是最容易踩坑的,因为它犯了一个低级错误:
doSomethingElse()是立即执行的,根本不会等doSomething完成!then方法需要接收的是一个函数(onFulfilled回调),但这里直接执行了doSomethingElse(),把它的返回值传给了then- 如果
doSomethingElse()返回的不是函数,then会把这个参数忽略(替换成默认的恒等函数,直接传递上一个Promise的值) - 哪怕
doSomethingElse()返回Promise,then也不会把它当成回调,而是直接处理这个Promise的结果
- 如果
例子:
// 执行这行代码时,doSomethingElse会立刻被调用,然后才开始执行doSomething doSomething() .then(doSomethingElse()) .then(result => console.log(result)); // 先触发doSomethingElse的执行,1秒后输出"doSomething done"
4. doSomething().then(doSomethingElse);
这是最简洁且正确的写法之一,和第一个写法的效果类似,但更优雅:
- 直接把
doSomethingElse函数引用传给then,当doSomething完成后,会自动调用doSomethingElse,并把doSomething的resolved值作为参数传给它 - 如果
doSomethingElse返回Promise,then会等待这个Promise完成,再推进链式调用 - 相比第一个写法,它不需要额外的匿名函数包裹,还能自动传递上一个Promise的结果,代码更简洁
例子:
function doSomethingElse(value) { console.log('收到上一步的值:', value); return new Promise(resolve => setTimeout(() => resolve('doSomethingElse done'), 1000)); } doSomething() .then(doSomethingElse) .then(result => console.log(result)); // 1秒后输出"收到上一步的值: doSomething done",再过1秒输出"doSomethingElse done"
总结一下关键点:
- 要等待异步操作,必须在
then的回调里返回对应的Promise - 传给
then的必须是函数引用,不能是立即执行的函数调用(除非你故意要提前执行) - 传递函数引用时,上一个Promise的结果会自动作为参数传入回调函数
内容的提问来源于stack exchange,提问作者Tarek Alkhatib
相关产品推荐
相关产品推荐

