我一直在使用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();
}
这很好用,但是有没有更简单的方法来做这件事呢?如果不是,这是否一个好的做法?
不,没有其他的方法来做这件事--我唯一能说的是这个用例并不是很常见。就像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
})