无法理解MDN Document中Promise.prototype.then()的注释

时间:2016-12-21 11:53:04

标签: node.js promise

我正在学习将我的Node.js代码样式从回调转换为承诺,这似乎是趋势并且在新概念中具有许多优点。 为了防止遗漏重要点并从中获益,我正在读书 document on MDN。我可以理解此页面中的示例,但不清楚几乎从一开始就提到的注意

  

注意:......如果省略第一个参数或提供非函数,       创建的新Promise简单地采用了履行状态       然后被召唤的承诺(如果它被实现)。如果       第二个参数被省略或提供了一个非函数,新的Promise即       创建简单地采用随后被调用的Promise的拒绝状态       on(如果它被拒绝)。

如果这是微不足道,请提前抱歉。 希望以实例解释,非常感谢。

3 个答案:

答案 0 :(得分:3)

编辑: 已更新以更好地符合规范 - 请参阅herehere

.then方法调用两个函数中的一个,具体取决于它附加的Promise是否已实现 。然后它根据该调用的结果返回一个新的Promise。这允许您根据Promise是否成功运行不同的逻辑,并且可以轻松地将Promise链接在一起。

但是,如果您决定不传递其中一个功能,它会使用合理的默认值 - 这就是您发布的注释所暗示的内容。尽管如此,演示可能要比描述容易得多!

如果您省略onRejected回调,请执行以下操作:

myPromise.then(function (value) {
    console.log("success!");
});

结果与执行此操作相同:

myPromise.then(function (value) {
    console.log("success!");
}, function (reason) {
    throw reason;
});

如果您省略onFulfilled回调,请执行以下操作:

myPromise.then(null, function (reason) {
    console.log("fail!");
});

结果与:

相同
myPromise.then(function (value) {
    return value; // the same as returning Promise.resolve(value)
}, function (reason) {
    console.log("fail!");
});

如果你把两者都抛弃......它基本上没有意义,但仍然是:

myPromise.then();

这实际上与以下内容相同:

myPromise.then(function (value) {
    return value;
}, function (reason) {
    throw reason;
});

反过来,基本上只是:

myPromise

答案 1 :(得分:2)

其他答案提供了很好的解释,但使用跳过的概念来表达它可能更容易。

  

如果承诺履行,则调用then第一个参数(只要它是一个函数);如果承诺拒绝,则调用then第二个参数(只要它在那里并且是一个函数)。在其他情况下,只会跳过.then

纯粹主义者会反对说.then是"跳过"是不正确的,而真正发生的事情是.then创造了一个等同的新承诺(或承担原始承诺的状态)。这在技术上是正确的,但非正式地更容易谈论和思考.then获得"跳过"。

示例:

function log(v) { console.log("value", v); }
function err(e) { console.log("error", e); }

Promise.resolve(1).then(null, err).then(log);
                   ^^^^^^^^^^^^^^^ "SKIPPED" (onFulfilled is null)

Promise.reject(1).then(log).catch(err);
                  ^^^^^^^^^        "SKIPPED" (onRejected is not given)

为完整起见,catch的相应行为是:

  

如果承诺拒绝,则调用catch的参数(只要它是一个函数)。在其他情况下,只会跳过.catch

Promise.resolve(1).catch(err).then(log);
                   ^^^^^^^^^^      "SKIPPED" (promise did not reject)

如果仔细考虑一下,您会发现这一切都意味着.then(null, handler) 完全等同于.catch(handler)的各种方式。所以catch可以被认为是一种便利例程。

但是,允许但忽略非功能处理程序的重点是什么?他们不应该抛出TypeError或其他东西吗?实际上,这是一个"功能"可以使用如下:

promise.then(isWednesday && wednesdayHandler)

如果是星期三,那么这将评估为wednesdayHandler,我们可以进行一些特殊的星期三处理。它不是星期三,那么这将评估为false,这显然不是一个函数,因此整个then子句将被"跳过"。

答案 2 :(得分:1)

我没有太多要补充的内容,其他答案还没有 - 只是我在写我自己的问题的过程中遇到了这个问题,此时如此奇迹般地提出了这个问题作为可能的重复项(在我之前的搜索尝试中没有出现时)。

无论如何,自 OP 以来,parameters to Promise.prototype.then 上关于 MDN 的当前文档已经发生了一些变化,我认为仍然令人困惑,如果不是比以前更混乱,所以我想我会添加一个关于当前文档,内容如下:

<块引用>

onFulfilled 可选

如果满足 Function,则调用 Promise。这个函数有一个参数,fulfillment value。如果它不是一个函数,它会在内部被一个“身份”函数替换(它返回接收到的参数)。

这个措辞令人困惑的是,“收到的论点”的前因是什么并不完全清楚。在不熟悉 Promises 规范的细节的情况下,您可以将其理解为“身份”函数,该函数返回 then() 调用接收到的参数。 IE。像这样的东西:

let promise = new Promise((resolve, reject) => resolve("value"));
let chained = promise.then("new value");

相当于:

let promise = new Promise((resolve, reject) => resolve("value"));
let chained = promise.then(() => "new_value");

因此从 chained 解析的值是 "new_value"

实际上,“接收值”是指链接 .then() 的原始承诺的解析值,即:

let promise = new Promise((resolve, reject) => resolve("value"));
let chained = promise.then(() => "value");

所以写 promise.then("not_a_callable") 完全忽略 "not a callable" 并解析为满足原始 promise 的值,无论它碰巧是什么。

就我个人而言,我认为这种令人困惑的行为,但事实就是如此。