我找到了“幽灵承诺”一词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);
});
答案 0 :(得分:2)
首先,我没有理由围绕这一点做出新的承诺。你的操作已经返回了promises,因此将error prone anti-pattern重新包装在一个新的承诺中。
其他人已经说过,.then()
处理程序有这些选择:
.then()
处理程序的结果。不返回任何内容会将undefined
传递给下一个.then()
处理程序。.then()
处理程序,否则被拒绝的值将被传递给下一个拒绝处理程序。 .then()
处理程序无法告诉promise链有条件地跳过除拒绝之外的一些.then()
个处理程序。
因此,如果您想根据某些条件逻辑分支您的承诺,那么您需要根据您的分支逻辑实际嵌套您的.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中,您仍然可以返回已有的承诺:
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(...)
答案 1 :(得分:1)
预期会有这种行为。当你链接.then()
语句时,除了抛出错误之外,你不能提前突破链。
您的顶级承诺(由Q.Promise()
返回的承诺)在_check()
之后得到解决;但实际上你有一个继续执行的内部承诺链。
根据规范,then()
会返回一个承诺:https://promisesaplus.com/#point-40
您可以在Q的源代码中看到自己:https://github.com/kriskowal/q/blob/v1/q.js#L899
对于您想要的行为,您实际上需要另一个嵌套的保证链。
return Q.Promise(function(resolve, reject) {
firstFunctionThatReturnPromise().then(function(firstResult) {
if (_check(firstResult)) {
resolve(firstResult);
} else {
return secondFunctionThatReturnPromise().then(function(secondResult) {
console.log(secondResult);
return thirdFunctionThatReturnPromise(secondResult);
});
}
});
});
答案 2 :(得分:0)
我从未使用过Q,但承诺返回的所有内容都会转换为承诺并传递给下一个.then()
。在这里,您的第一个.then()
不会返回任何内容。所以它返回undefined
。因此undefined
包含在新Promise
中并传递给下一个处理程序,您将获得secondResult == undefined
。
您可以在以下CodePen中查看它:http://codepen.io/JesmoDrazik/pen/xOaXKE