Promise puzzles

Twitter上的一个问题,起先是在知乎一篇专栏上看到的。问下列代码的执行顺序

Promise-puzzles

这里没有定义doSomethingdoSomethingElse, 所以puzzle #3的解释可能不一样。 先给出下面的定义:

function doSomething() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('something');
        }, 1000);
    });
}

function doSomethingElse() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('somethingElse');
        }, 1500);
    });
}

Puzzle #1

console.time('case 1')
doSomething().then(() => {
    return doSomethingElse()
}).then(function finalHandler(res) {
    console.log(res)
    console.timeEnd('case 1')
})
  • 打印信息为
    somethingElse
    case 1: 2511.396ms
    
  • 执行顺序为
    doSomething()
    |----------|
               doSomethingElse()
               |---------------|
                               finalHandler(somethingElse)
                               |->
    
  • 这是正常写promise的代码

Puzzle #2

console.time('case 2')
doSomething().then(() => {
    doSomethingElse()
}).then(function finalHandler(res) {
    console.log(res)
    console.timeEnd('case 2')
})
  • 打印信息
    undefined
    case 2: 1016.124ms
    
  • 执行顺序
    doSomething()
    |----------|
               doSomethingElse()
               |---------------|
               finalHandler(undefined)
               |->
    
  • 这里相比Puzzle #1 在then中去掉了return ,所以doSomethingElse 是异步执行的。而没有return任何值,所以finalHandler中为undefined

Puzzle #3

console.time('case 3')
doSomething().then(
    doSomethingElse()
).then(function finalHandler(res) {
    console.log(res)
    console.timeEnd('case 3')
})
  • 打印信息
    something
    case 3: 1021.446ms
    
  • 执行顺序
    doSomething()
    |----------|
    doSomethingElse()
    |---------------|
               finalHandler(something)
               |->
    
  • 这里发生了值穿透??,看了这个后还是有点不太明白。doSomethingElse这里不会等待doSomething执行完毕后执行么
  • then需要接受一个函数,这里却传了一个值

这里如果doSomethingElse返回的是一个函数,结果就不一样了

function doSomethingElse() {
    return () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('somethingElse');
            }, 1500);
        });
    }
}
  • 打印信息:
    somethingElse
    case 3: 2522.012ms
    
  • 执行顺序
    doSomething()
    |----------|
    doSomethingElse()
    |----------------|
                     finalHandler(something)
                     |->
    

Puzzle #4

console.time('case 4')
doSomething().then(doSomethingElse)
    .then(function finalHandler(res) {
        console.log(res)
        console.timeEnd('case 4')
    })
  • 打印结果:
    somethingElse
    case 4: 2537.144ms
    
  • 执行顺序
    doSomething()
    |----------|
               doSomethingElse(something)
               |---------------|
                               finalHandler(somethingElse)
                               |->
    
  • 这里给then传递都还是一个函数,所以和Puzzle #1的结果是一样的