在Angular中,以下代码段似乎相同:
let deferred = $q.defer();
if(whatever) {
deferred.resolve('something');
}
else {
deferred.reject('nah');
}
return deferred.promise;
和
return $q((resolve,reject) => {
if(whatever) {
resolve('something');
}
else {
reject('nah');
}
});
我的问题:如果它们不相同,它们有何不同?如果它们是等价的,是否有令人信服的理由选择一个而不是另一个?
答案 0 :(得分:5)
您发布的第二个版本是遵循Promise/A+ - 规范的版本。
从功能角度来看,两个版本都是等价的。第一个版本(在我看来)使得更容易将异步代码读取为同步代码,但第二个版本使用将其作为ES2015的语法,并且也将成为ES6的一部分,即下一个版本的的JavaScript。
因此,选择取决于您,但您可以期待在未来看到更多第二种类型的promise语法。
答案 1 :(得分:3)
就$q
承诺而言,一个与另一个之间没有巨大的行为差异。第二种方法的主要好处是它使用与本机承诺相同的样式,它很好地包含了解决承诺的逻辑,而不是松散的延迟悬空(这可能是本机承诺与之相关的原因之一)后一种风格)。
我错误地说第二种方法会捕获传入函数中的同步错误并将它们转换为被拒绝的承诺。对于本地承诺,Q承诺,Bluebird承诺以及可能的其他承诺都是如此,但$q()
并非如此。 $q
只会将错误视为未捕获的错误,并将其记录到控制台。
这是一个使用Bluebird承诺的例子,我所描述的内容。如果您使用的是$q
以外的承诺,那么使用后一种风格是一个很好的理由:
function queryValue(callback) {
throw new Error("Not implemented yet!!!");
}
function makeConstructorPromise() {
return new Promise(function(resolve) {
queryValue(function(value) {
resolve(value);
});
});
}
function makeDeferredPromise() {
let deferred = Promise.defer();
queryValue(function(value) {
deferred.resolve(value);
});
return deferred.promise;
}
makeConstructorPromise()
.catch(function(error) {
console.error('caught the constructed promise error!', error);
});
makeDeferredPromise()
.catch(function(error) {
// not caught
console.error('caught the deferred promise error!', error);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.5.1/bluebird.min.js"></script>
延迟方法是老式的,可能在非常具体的情况下具有实际应用,但99%的情况下,构造方法是可行的方法。
它更安全(在大多数承诺实施中)并且与ES6承诺的工作方式一致。
答案 2 :(得分:0)
功能相当 - 更多关于&#34;风格&#34;。
一种语法更像Kris Kowals Q,这是javascript中最早的承诺实现之一。
另一种语法更像是我们将通过ES6获得的实现。
所以使用,你更熟悉的东西 - 如果你开始学习,我建议使用ES6方式,因为这将是&#34;标准javascript&#34;而且不仅仅是棱角分明。
有关此主题和您的问题的更多信息,您可以直接在Angualar Docu中找到: https://docs.angularjs.org/api/ng/service/ $ Q /