为什么可以将非函数参数传递给 Promise.then() 而不会导致错误?

nev*_*gqs 4 javascript node.js promise

我有以下几点:

new Promise(resolve => setTimeout(resolve, 2000))
    .then(() => console.log("after 2 seconds"));

new Promise(resolve => setTimeout(resolve, 3000))
    .then(console.log("before 3 seconds (instantly)"));
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

> node index.js
before 3 seconds (instantly)
after 2 seconds
Run Code Online (Sandbox Code Playgroud)

Promise.then()需要一个onFulfilled函数,但我传入的console.log("before 2 seconds (instantly)")不是函数。两部分问题:

  • 为什么console.log("before 2 seconds (instantly)")会立即执行(或根本执行)?
  • 当我没有传入函数时,为什么第二个 Promise 没有引发异常?

Poi*_*nty 5

编码

console.log("before 3 seconds (instantly)")
Run Code Online (Sandbox Code Playgroud)

是一个表达式,特别是一个函数调用表达式。无论出现在何处,它都意味着相同的事情,包括作为.then()Promise 方法的参数的外观。与任何其他类似语言一样,函数调用中使用的表达式在函数调用之前进行评估,因此

.then(console.log("before 3 seconds (instantly)"))
Run Code Online (Sandbox Code Playgroud)

导致首先console.log()调用函数,然后将返回值传递给. 这就是为什么您会立即在控制台中看到该消息的原因。.then()

允许传递undefined.then(),并且由于这是console.log()返回的内容,因此不会引发错误。

如果您希望console.log()在 Promise 完成时发生这种情况,您可以将它包装在一个函数中:

.then(function() { console.log("after 3 seconds"); })
Run Code Online (Sandbox Code Playgroud)


rsp*_*rsp 4

为什么可以将非函数参数传递给 Promise.then() 而不会导致错误?

是的。所有非函数参数都应被忽略。见下文。

为什么 console.log(“2 秒前(立即)”) 立即(或根本)执行?

因为在 JS 中,函数调用的参数是立即求值的(应用顺序)。

为什么当我没有传入函数时,第二个 Promise 没有引发异常?

因为console.log返回undefined且不.then()带参数是合法的(因为两个处理程序都是可选的)。在您的示例中console.log()返回未定义,因此就像.then()不带参数的调用一样。

但即使使用一些不是函数的参数调用它,它们仍然会被忽略。例如,即使在这个例子中,“ok”仍然会到达console.log最后,这可能会令人惊讶:

Promise.resolve('ok')
    .then()
    .then(false)
    .then(null)
    .then(1)
    .then('x')
    .then([1, 2, 3])
    .then({a: 1, b: 2})
    .then(console.log);
Run Code Online (Sandbox Code Playgroud)

请参阅Promises/A+规范第 2.2.1 节,其中描述了该.then()方法的参数:

2.2.1 onFulfilled 和 onRejected 都是可选参数:

  • 如果 onFulfilled 不是函数,则必须忽略它。
  • 如果 onRejected 不是函数,则必须忽略它。