简化Javascript中的承诺

Mis*_*hko 7 javascript promise angularjs angular-promise

以下代码片段是否相同?

版本1

function doSomething() {
  var defer = $q.defer();

  foo().then(function() {
    bar().then(function() {
      defer.resolve();
    });
  });

  return defer.promise;
}
Run Code Online (Sandbox Code Playgroud)

版本2

function doSomething() {
  return foo().then(bar);
}
Run Code Online (Sandbox Code Playgroud)

Wil*_*eer 6

这两种方法之间存在许多差异.

两个片段之间的主要区别在于,version 2您将隐式地将已解析的值foo直接传递给bar.除此之外,doSomething将解决bar将要解决的任何问题,而在version 1结果中将被丢弃.

Benjamin Gruenbaum提出的一些重要观点:

(a)如果bar是引用错误1,则拒绝内部承诺和2次抛出.
(b)1要求引用$ q,其中2是与实现无关的.
(c)版本1不是例外安全的,如果版本2允许您拒绝,则会拒绝拒绝.; 还有一些较小的差异.请参见stackoverflow.com/questions/22539815

你也可以这样写.
这样,您就不由得解析值隐含的通槽foo,以bar(它现在是明确的),这可能会造成混淆或容易被忽视.如果您想要在返回它们之前foobar之前使用已解析的值执行某些操作,它也会很有用.

function doSomething() {
  return foo().then(function(res){
     // maybe  do something with the result of foo
     return bar(res);
  }).then(function(res){
     // maybe do something with the result of bar
     return res;
  });
}
Run Code Online (Sandbox Code Playgroud)

手动创建延迟对象应该保持最小,通常是反模式.

https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#the-deferred-anti-pattern

这里展示的关键原则是,promise将在其解析方法中采用返回的promise(或者thenable)的状态.

  • @Sprottenwels看到http://stackoverflow.com/questions/23803743/what-is-the-deferred-anti-pattern-and-how-do-i-avoid-it你应该只创建递延对象promisifying的API或写入时聚合方法 - 很少这种情况.例如,我有一个100KLoC代码库与Bluebird没有一个延迟或承诺构造函数. (2认同)