Promise中两种函数传值的区别

102 阅读2分钟

定义一个 openDialog 函数,有如下两种写法:

async function openDialog1() {
    return doSomething()
        .then(() => Promise.resolve())
        .catch(() => Promise.reject());
}

async function openDialog2() {
    return doSomething()
        .then(Promise.resolve)
        .catch(Promise.reject);
}

这两个函数看起来很相似,但它们的行为有一些细微的区别,主要体现在 .then().catch() 的写法以及它们的返回值处理上。

1. 第一个函数:openDialog1

async function openDialog1() {
    return doSomething()
        .then(() => Promise.resolve())
        .catch(() => Promise.reject());
}
  • .then(() => Promise.resolve())
    这里 then 接受的是一个匿名函数,该函数返回 Promise.resolve()。因此,doSomething() 成功时,then 会返回一个显式的 Promise.resolve()

  • .catch(() => Promise.reject())
    同样,catch 也接受一个匿名函数,这个函数返回 Promise.reject()。因此,doSomething() 失败时,catch 会返回一个显式的 Promise.reject()

  • 行为总结

    • 如果 doSomething() 成功,openDialog1 将返回一个已解决的 Promise。
    • 如果 doSomething() 失败,openDialog1 将返回一个被拒绝的 Promise。

2. 第二个函数:openDialog2

async function openDialog2() {
    return doSomething()
        .then(Promise.resolve)
        .catch(Promise.reject);
}
  • .then(Promise.resolve)
    这里 then 中传递的是 Promise.resolve 本身,而不是一个返回 Promise.resolve() 的函数。这意味着 Promise.resolve 函数被直接传递,而不是在 then 被调用时执行。

    潜在问题
    这样做的问题在于 Promise.resolve 是一个构造函数,它会将当前传入的参数作为其参数,甚至会忽略之前 doSomething() 的结果,并立即返回一个已解决的 Promise。如果 doSomething() 成功执行,Promise.resolve 会被立即执行,而不会等待任何结果。

  • .catch(Promise.reject)
    类似于 then,这里的 catch 直接传递了 Promise.reject。它的行为是当 doSomething() 失败时,Promise.reject 将立即执行,传入的错误也会被忽略。

  • 行为总结

    • 如果 doSomething() 成功,Promise.resolve 会立即被调用并返回一个已经解决的 Promise,且不会传递 doSomething() 的结果。
    • 如果 doSomething() 失败,Promise.reject 会被立即调用,且传递给 reject 的参数是 Promise.reject 本身的行为。

关键区别:

  1. 匿名函数 vs 直接传递函数引用

    • openDialog1 使用了匿名函数包装 Promise.resolve()Promise.reject(),因此 thencatch 是在适当的时候调用这些函数。
    • openDialog2 直接传递了 Promise.resolvePromise.reject,这些函数会立即执行并忽略它们接收到的参数。
  2. 处理结果的方式

    • openDialog1 可以明确处理 doSomething() 的结果(即使没有使用它),并在需要时返回显式的 Promise.resolve()Promise.reject()
    • openDialog2 的写法会导致 thencatch 在成功或失败时立即执行,不会考虑 doSomething() 返回的任何结果或错误,甚至会忽略那些值。

结论:

  • openDialog1 是正确且可预期的写法,它正确地封装了 Promise.resolvePromise.reject,并且处理流程较为明确。
  • openDialog2 可能会导致意外行为,特别是在 thencatch 中忽略了返回的值,且其行为更加不明确。