提问者:小点点

解析函数作用域之外的Javascriptpromise


我一直在使用ES6承诺。

通常,承诺的构造和使用方式如下

new Promise(function(resolve, reject){
    if (someCondition){
        resolve();
    } else {
        reject();
    } 
});

但为了灵活起见,我一直在做一些类似下面的事情,把决心放在外面。

var outsideResolve;
var outsideReject;
new Promise(function(resolve, reject) { 
    outsideResolve = resolve; 
    outsideReject = reject; 
});

以及以后

onClick = function(){
    outsideResolve();
}

这很好用,但是有没有更简单的方法来做这件事呢?如果不是,这是否一个好的做法?


共3个答案

匿名用户

不,没有其他的方法来做这件事--我唯一能说的是这个用例并不是很常见。就像Felix在评论中所说的那样--你所做的事情将始终如一地奏效。

值得一提的是,promise构造函数这样做的原因是抛出安全性--如果代码在promise构造函数中运行时发生了您没有预料到的异常,它将转变为拒绝,这种形式的抛出安全性--将抛出的错误转换为拒绝非常重要,并且有助于维护可预测的代码。

出于抛出安全性的考虑,选择了promise构造函数而不是Deferred(Deferred是一种允许您正在做的事情的另一种promise构造方法)作为最佳实践,我将传递元素并使用promise构造函数:

var p = new Promise(function(resolve, reject){
    this.onclick = resolve;
}.bind(this));

出于这个原因,每当您可以使用promise构造函数导出函数时,我建议您使用它。当你可以避免两者的时候--避免两者和锁链。

请注意,对于if(condition)这样的事情,您永远不应该使用promise构造函数,第一个示例可以写成:

var p = Promise[(someCondition)?"resolve":"reject"]();

匿名用户

简单:

var promiseResolve, promiseReject;

var promise = new Promise(function(resolve, reject){
  promiseResolve = resolve;
  promiseReject = reject;
});

promiseResolve();

匿名用户

这里的聚会有点晚了,但另一种方法是使用延迟对象。实际上,您有相同数量的样板,但是如果您想要传递它们并且可能解析出它们的定义之外,那么这是很方便的。

朴素实现:

class Deferred {
  constructor() {
    this.promise = new Promise((resolve, reject)=> {
      this.reject = reject
      this.resolve = resolve
    })
  }
}

function asyncAction() {
  var dfd = new Deferred()

  setTimeout(()=> {
    dfd.resolve(42)
  }, 500)

  return dfd.promise
}

asyncAction().then(result => {
  console.log(result) // 42
})

ES5版本:

function Deferred() {
  var self = this;
  this.promise = new Promise(function(resolve, reject) {
    self.reject = reject
    self.resolve = resolve
  })
}

function asyncAction() {
  var dfd = new Deferred()

  setTimeout(function() {
    dfd.resolve(42)
  }, 500)

  return dfd.promise
}

asyncAction().then(function(result) {
  console.log(result) // 42
})