Mor*_*rio 248 javascript promise es6-promise
我一直在使用ES6 Promise.
通常,Promise是这样构造和使用的
new Promise(function(resolve, reject){
if (someCondition){
resolve();
} else {
reject();
}
});
Run Code Online (Sandbox Code Playgroud)
但我一直在做类似下面的事情,为了灵活性而采取外面的决心.
var outsideResolve;
var outsideReject;
new Promise(function(resolve, reject) {
outsideResolve = resolve;
outsideReject = reject;
});
Run Code Online (Sandbox Code Playgroud)
然后
onClick = function(){
outsideResolve();
}
Run Code Online (Sandbox Code Playgroud)
这很好,但是有更简单的方法吗?如果没有,这是一个好习惯吗?
car*_*ter 114
简单:
var promiseResolve, promiseReject;
var promise = new Promise(function(resolve, reject){
promiseResolve = resolve;
promiseReject = reject;
});
promiseResolve();
Run Code Online (Sandbox Code Playgroud)
Jon*_*ues 85
这里的派对迟到了,但另一种方法是使用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
})
Run Code Online (Sandbox Code Playgroud)
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
})
Run Code Online (Sandbox Code Playgroud)
Ben*_*aum 83
不,没有其他方法可以做到这一点 - 我唯一可以说的是这个用例并不常见.就像菲利克斯在评论中所说的那样 - 你所做的将会持续发挥作用.
值得一提的是,promise构造函数以这种方式运行的原因是抛出安全性 - 如果您在代码在promise构造函数内运行时没有预料到会发生异常,它将变成拒绝,这种抛出安全形式 - 将抛出的错误转换为拒绝很重要,有助于维护可预测的代码.
对于这个抛出安全原因,promise构造函数被选择为延迟(这是一种替代的承诺构造方式,允许你正在做的事情) - 至于最佳实践 - 我将传递元素并使用promise构造函数:
var p = new Promise(function(resolve, reject){
this.onclick = resolve;
}.bind(this));
Run Code Online (Sandbox Code Playgroud)
出于这个原因 - 每当你可以使用promise构造函数而不是导出函数时 - 我建议你使用它.每当你可以避免两者 - 避免两者和链.
注意,你应该永远不要使用promise构造函数if(condition)
,第一个例子可以写成:
var p = Promise[(someCondition)?"resolve":"reject"]();
Run Code Online (Sandbox Code Playgroud)
Max*_*mus 18
我在2015年为我的框架提出的解决方案.我称这种承诺为任务
function createPromise(handler){
var _resolve, _reject;
var promise = new Promise(function(resolve, reject){
_resolve = resolve;
_reject = reject;
handler(resolve, reject);
})
promise.resolve = _resolve;
promise.reject = _reject;
return promise;
}
var promise = createPromise()
promise.then(function(data){ alert(data) })
promise.resolve(200) // resolve from outside
Run Code Online (Sandbox Code Playgroud)
小智 16
以防万一有人来寻找简化此任务的 util 的打字稿版本:
export const deferred = <T>() => {
let resolve!: (value: T | PromiseLike<T>) => void;
let reject!: (reason?: any) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return {
resolve,
reject,
promise,
};
};
Run Code Online (Sandbox Code Playgroud)
这可以使用,例如。喜欢:
const {promise, resolve} = deferred<string>();
promise.then((value) => console.log(value)); // nothing
resolve('foo'); // console.log: foo
Run Code Online (Sandbox Code Playgroud)
Ali*_*Ali 15
接受的答案是错误的。使用范围和引用非常容易,尽管它可能会让 Promise纯粹主义者生气:
const createPromise = () => {
let resolver;
return [
new Promise((resolve, reject) => {
resolver = resolve;
}),
resolver,
];
};
const [ promise, resolver ] = createPromise();
promise.then(value => console.log(value));
setTimeout(() => resolver('foo'), 1000);
Run Code Online (Sandbox Code Playgroud)
我们本质上是在创建 Promise 时获取对 resolve 函数的引用,然后我们返回它以便可以在外部设置它。
一秒钟后,控制台将输出:
> foo
Run Code Online (Sandbox Code Playgroud)
Ric*_*ler 14
我喜欢@JonJaques的回答,但我想更进一步.
如果绑定then
和catch
随后的Deferred
对象,那么它完全实现了Promise
API,你可以把它当作承诺,await
它与这样的.
class DeferredPromise {
constructor() {
this._promise = new Promise((resolve, reject) => {
// assign the resolve and reject functions to `this`
// making them usable on the class instance
this.resolve = resolve;
this.reject = reject;
});
// bind `then` and `catch` to implement the same interface as Promise
this.then = this._promise.then.bind(this._promise);
this.catch = this._promise.catch.bind(this._promise);
this[Symbol.toStringTag] = 'Promise';
}
}
const deferred = new DeferredPromise();
console.log('waiting 2 seconds...');
setTimeout(() => {
deferred.resolve('whoa!');
}, 2000);
async function someAsyncFunction() {
const value = await deferred;
console.log(value);
}
someAsyncFunction();
Run Code Online (Sandbox Code Playgroud)
Cor*_*son 10
辅助方法可以减轻这些额外的开销,并为您提供相同的jQuery感觉.
function Deferred() {
let resolve;
let reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
}
Run Code Online (Sandbox Code Playgroud)
用法是
const { promise, resolve, reject } = Deferred();
displayConfirmationDialog({
confirm: resolve,
cancel: reject
});
return promise;
Run Code Online (Sandbox Code Playgroud)
这与jQuery类似
const dfd = $.Deferred();
displayConfirmationDialog({
confirm: dfd.resolve,
cancel: dfd.reject
});
return dfd.promise();
Run Code Online (Sandbox Code Playgroud)
虽然,在一个用例中,这种简单的原生语法很好
return new Promise((resolve, reject) => {
displayConfirmationDialog({
confirm: resolve,
cancel: reject
});
});
Run Code Online (Sandbox Code Playgroud)
这里的许多答案都类似于在最后一个例子这篇文章。我正在缓存多个 Promise,并且可以将resolve()
和reject()
函数分配给任何变量或属性。因此,我可以使这段代码稍微紧凑一些:
function defer(obj) {
obj.promise = new Promise((resolve, reject) => {
obj.resolve = resolve;
obj.reject = reject;
});
}
Run Code Online (Sandbox Code Playgroud)
以下是使用此版本defer()
将FontFace
负载 Promise 与另一个异步进程组合的简化示例:
function onDOMContentLoaded(evt) {
let all = []; // array of Promises
glob = {}; // global object used elsewhere
defer(glob);
all.push(glob.promise);
// launch async process with callback = resolveGlob()
const myFont = new FontFace("myFont", "url(myFont.woff2)");
document.fonts.add(myFont);
myFont.load();
all.push[myFont];
Promise.all(all).then(() => { runIt(); }, (v) => { alert(v); });
}
//...
function resolveGlob() {
glob.resolve();
}
function runIt() {} // runs after all promises resolved
Run Code Online (Sandbox Code Playgroud)
更新:如果您想封装对象,有两种选择:
function defer(obj = {}) {
obj.promise = new Promise((resolve, reject) => {
obj.resolve = resolve;
obj.reject = reject;
});
return obj;
}
let deferred = defer();
Run Code Online (Sandbox Code Playgroud)
和
class Deferred {
constructor() {
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
}
let deferred = new Deferred();
Run Code Online (Sandbox Code Playgroud)
小智 8
在某些情况下,我发现自己也缺少延迟模式。你总是可以在 ES6 Promise 之上创建一个:
export default class Deferred<T> {
private _resolve: (value: T) => void = () => {};
private _reject: (value: T) => void = () => {};
private _promise: Promise<T> = new Promise<T>((resolve, reject) => {
this._reject = reject;
this._resolve = resolve;
})
public get promise(): Promise<T> {
return this._promise;
}
public resolve(value: T) {
this._resolve(value);
}
public reject(value: T) {
this._reject(value);
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用辅助函数来创建我称之为"扁平承诺"的东西 -
function flatPromise() {
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
}
Run Code Online (Sandbox Code Playgroud)
而我正在使用它 -
function doSomethingAsync() {
// Get your promise and callbacks
const { resolve, reject, promise } = flatPromise();
// Do something amazing...
setTimeout(() => {
resolve('done!');
}, 500);
// Pass your promise to the world
return promise;
}
Run Code Online (Sandbox Code Playgroud)
查看完整的工作示例 -
function flatPromise() {
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
}
function doSomethingAsync() {
// Get your promise and callbacks
const { resolve, reject, promise } = flatPromise();
// Do something amazing...
setTimeout(() => {
resolve('done!');
}, 500);
// Pass your promise to the world
return promise;
}
(async function run() {
const result = await doSomethingAsync()
.catch(err => console.error('rejected with', err));
console.log(result);
})();
Run Code Online (Sandbox Code Playgroud)
编辑:我创建了一个名为flat-promise的NPM包,代码也可以在GitHub上找到.
您可以将Promise包装在一个类中。
class Deferred {
constructor(handler) {
this.promise = new Promise((resolve, reject) => {
this.reject = reject;
this.resolve = resolve;
handler(resolve, reject);
});
this.promise.resolve = this.resolve;
this.promise.reject = this.reject;
return this.promise;
}
promise;
resolve;
reject;
}
// How to use.
const promise = new Deferred((resolve, reject) => {
// Use like normal Promise.
});
promise.resolve(); // Resolve from any context.
Run Code Online (Sandbox Code Playgroud)
我们的解决方案是使用闭包来存储解析/拒绝函数,并另外附加一个函数来扩展承诺本身。
这是模式:
function getPromise() {
var _resolve, _reject;
var promise = new Promise((resolve, reject) => {
_reject = reject;
_resolve = resolve;
});
promise.resolve_ex = (value) => {
_resolve(value);
};
promise.reject_ex = (value) => {
_reject(value);
};
return promise;
}
Run Code Online (Sandbox Code Playgroud)
并使用它:
var promise = getPromise();
promise.then(value => {
console.info('The promise has been fulfilled: ' + value);
});
promise.resolve_ex('hello');
// or the reject version
//promise.reject_ex('goodbye');
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
66063 次 |
最近记录: |