我一直在使用ES6 Promise。
通常,Promise是这样构造和使用的
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();
}
这很好,但是否有更简单的方法来做到这一点?如果不是,这是一个好的实践吗?
如果(像我一样)你不喜欢增强本地实例,也不笨重”。承诺“属性……但是如果你喜欢代理和破坏类,那么这个是给你的:
class GroovyPromise {
constructor() {
return new Proxy(new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
}), {
get: (target, prop) =>
this[prop] || target[prop].bind(target),
});
}
}
这样用:
const groovypromise = new GroovyPromise();
setTimeout(() => groovypromise.resolve('groovy'), 1000);
console.log(await groovypromise);
当然,你也可以将类重命名为“Deferred”
有点晚了,但另一种方法是使用Deferred对象。你基本上有相同数量的样板文件,但是如果你想要传递它们并且可能在它们的定义之外解析,这很方便。
天真的实现:
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
})
我为此写了一个小库。https://www.npmjs.com/package/@inf3rno/promise.exposed
我使用了别人写的工厂方法,但是我也重写了then, catch, finally方法,所以你也可以通过这些方法解决原来的承诺。
在没有外部执行人的情况下解决承诺:
const promise = Promise.exposed().then(console.log);
promise.resolve("This should show up in the console.");
从外部与执行器的setTimeout赛跑:
const promise = Promise.exposed(function (resolve, reject){
setTimeout(function (){
resolve("I almost fell asleep.")
}, 100000);
}).then(console.log);
setTimeout(function (){
promise.resolve("I don't want to wait that much.");
}, 100);
如果你不想污染全局命名空间,有一个无冲突模式:
const createExposedPromise = require("@inf3rno/promise.exposed/noConflict");
const promise = createExposedPromise().then(console.log);
promise.resolve("This should show up in the console.");