javascript - 如何修复 promise 反模式 - Ghost Promise?

标签 javascript promise

我找到了术语“The Ghost Promise” here ,这看起来像我的情况。

我有这样的代码:

return Q.Promise(function(resolve, reject) {
  firstFunctionThatReturnPromise()
  .then(function(firstResult) {
    _check(firstResult) ? resolve(firstResult) : return secondFunctionThatReturnPromise();
  })
  .then(function(secondResult) {
    console.log(secondResult);
    return thirdFunctionThatReturnPromise(secondResult);
  })
  .then(function(thirdResult) {
    resolve(thirdResult);
  })
  .catch(function(e) {
    reject(e)
  });
});

问题是,即使 _check 返回 true,它仍会继续执行 console.log 命令(导致 undefined) .

如果 _check 返回 false,则一切正常。

所以我的问题是:

  • 上述行为是否正常?
  • 是否有更优雅的方式来处理这种情况?

更新 1: 许多人质疑为什么我使用 Q.Promise 而不是直接返回结果。这是因为这是一个通用函数,由其他函数共享。

// Usage in other functions
genericFunction()
.then(function(finalResult) {
   doSomething(finalResult);
})
.catch(function(err) {
   handleError(err);
});

最佳答案

首先,没有理由围绕这些做出新的 promise 。您的操作已经返回 promise ,因此它是 error prone anti-pattern用新的 promise 重新包装它们。

其次,正如其他人所说,.then() 处理程序有以下选择:

  1. 它可以返回一个结果,该结果将传递给下一个 .then() 处理程序。不返回任何东西将 undefined 传递给下一个 .then() 处理程序。
  2. 它可以返回一个 promise ,其解析值将传递给下一个 .then() 处理程序,或者拒绝值将传递给下一个拒绝处理程序。
  3. 它可以抛出 which 将拒绝当前的 promise。

除了拒绝之外,.then() 处理程序无法告诉 promise 链有条件地跳过一些后续的 .then() 处理程序。

因此,如果您想根据某些条件逻辑分支您的 promise,那么您实际上需要根据您的分支逻辑嵌套您的 .then() 处理程序:

a().then(function(result1) {
    if (result1) {
        return result1;
    } else {
        // b() is only executed here in this conditional
        return b().then(...);
    }
}).then(function(result2) {
    // as long as no rejection, this is executed for both branches of the above conditional
    // result2 will either be result1 or the resolved value of b()
    // depending upon your conditional
})

因此,当您想要分支时,您可以创建一个新的嵌套链,让您可以根据条件分支控制发生的事情。

使用你的伪代码,它看起来像这样:

firstFunctionThatReturnPromise().then(function (firstResult) {
    if (_check(firstResult)) {
        return firstResult;
    } else {
        return secondFunctionThatReturnPromise().then(function (secondResult) {
            console.log(secondResult);
            return thirdFunctionThatReturnPromise(secondResult);
        })
    }
}).then(function (finalResult) {
    console.log(finalResult);
    return finalResult;
}).catch(function (err) {
    console.log(err);
    throw err;
});

即使这是在 genericFunction 中,您仍然可以只返回您已经拥有的 promise :

function genericFunction() {
    return firstFunctionThatReturnPromise().then(function (firstResult) {
        if (_check(firstResult)) {
            return firstResult;
        } else {
            return secondFunctionThatReturnPromise().then(function (secondResult) {
                console.log(secondResult);
                return thirdFunctionThatReturnPromise(secondResult);
            })
        }
    }).then(function (finalResult) {
        console.log(finalResult);
        return finalResult;
    }).catch(function (err) {
        console.log(err);
        throw err;
    });
}

// usage
genericFunction().then(...).catch(...)

关于javascript - 如何修复 promise 反模式 - Ghost Promise?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38724752/

相关文章:

javascript - 重构一个使用 window.open 来使用 DOM 而不是 write() 的函数

javascript - 获取此 contenteditable 元素中的当前行和行索引?

javascript - JQuery从函数到其他JQuery函数的传递编号

javascript - promise then方法中返回一个Promise对象时的执行顺序

javascript - Import'd React.Component 不使用 Typescript 渲染

javascript - 用于匹配输入的正则表达式,例如 HTML 输入中模式的 "abc > 10, cba < 100, ..."

javascript - 无法读取未定义和未处理的 promise 拒绝的属性 'catch'

javascript - 在 Ember 中编写 promise

javascript - 在 Ember 中使用 promise

javascript - forEach 内部 promise 的结果