不理解javascript promise antipattern,从回调中返回promise

时间:2014-07-12 00:18:13

标签: javascript promise

有人可以向我解释为什么在承诺回调中返回承诺会被视为反模式吗?显然它打破了异常冒泡,但显然我对承诺的理解是缺乏的,因为我无法清楚地描述如何工作。我的反模式代码如下:

var a = new Promise(function (res, rej) {

    setTimeout(function () {
        res("timeout");
    }, 1000);

});

a.then(function (res) {
    console.log("a");
    console.log(res);

    return new Promise(function (res, rej) {
        console.log("b");
        setTimeout(function () {
            res("timeout2");
        }, 2000);
    }).then(function (res) {
        console.log("c");
        console.log(res);

    }).then(function (res) {
        console.log("d");
        console.log(res);

    }, function (res) {
        console.log("e");
        console.log(res);

    });

}).then(function (res) {
    console.log("l");
    console.log(res);
});

编辑:

这个问题与我的previous questions之一有关,我在其中做了类似承诺的事情,其中​​一个答案说:

"你也必须永远不要将回调与promises混合,因为这样你就会失去异常冒泡(承诺点)并使你的代码变得非常冗长。"

所以现在我真的很困惑,如果它是反模式,如果是这样的话。

1 个答案:

答案 0 :(得分:4)

“你也必须永远不要将回调与promises混合在一起,因为这样你就会失去异常冒泡(承诺点)并使你的代码变得非常冗长。”

Petka在这里的意思是,你不应该在你的用户代码中使用基于回调的方法和Promises,因为这会使你的代码非常冗长,如你的例子所示。

这很冗长,因为每次调用函数时都必须根据回调手动解析或拒绝新的Promise。

setTimeout示例:
超时完成后,您必须手动调用解析程序。 现在setTimeout是一个很糟糕的例子,因为它没有可能拒绝它的操作。

return new Promise(function (resolve, reject) {
        console.log("b");
        setTimeout(function () {
            resolve("timeout2");
        }, 2000);
    })

更好的例子
假设你想这样打fs.readFile

return new Promise(function (resolve, reject) {
    fs.readFile('foo.txt', function (err, res) {
        if (err){
            reject(err);
            return;
        } else {
            resolve(res);
        }
    });
})

在这里你必须解决或拒绝,因为你将promises与回调混合,这将使你的代码变得非常脆弱和混乱。

<强>解决方案:

当您需要调用仅支持回调的方法时,不要在整个地方创建新的Promise,而是将基于回调的方法包装一次并在任何地方使用它。

var readFileAsync = new Promise(function (resolve, reject) {
    fs.readFile('foo.txt', function (err, res) {
        if (err){
            reject(err);
            return;
        } else {
            resolve(res);
        }
    });
});

<强>加成:

你甚至不需要这样做包裹你的自己,蓝鸟已经让你满意。 结账宣传就在这里:

https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification

除了在promise的onFulfilled方法中返回Promise完全有效之外,这个整体解释也是如此。 这是Promise / A +规范的一部分,请参阅The Promise Resolution Procedure - &gt; 2.3.2 If x is a promise, adopt its state [[3.4](#notes)]:

我认为你的困惑源于Petka告诉你不要在你的例子中创造并返回新的承诺。但这与你回归Promise的事实无关,而是与你不应该在那个地方创造承诺的事实有关,如上所述。

使用包装版本,然后您可以在任何地方返回/链接它们。