创建一个(ES6)承诺而不开始解决它
Creating a (ES6) promise without starting to resolve it
使用 ES6 承诺,如何在不定义解析逻辑的情况下创建承诺?这是一个基本示例(一些 TypeScript):
var promises = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return promises[key];
}
var promise = new Promise(resolve => {
// But I don't want to try resolving anything here :(
});
promises[key] = promise;
return promise;
}
function resolveWith(key: string, value: any): void {
promises[key].resolve(value); // Not valid :(
}
使用其他 promise 库可以轻松完成。 JQuery例如:
var deferreds = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return deferreds[key].promise();
}
var def = $.Deferred();
deferreds[key] = def;
return def.promise();
}
function resolveWith(key: string, value: any): void {
deferreds[key].resolve(value);
}
我能看到的唯一方法是将 resolve 函数存储在 promise 的执行程序中的某个地方,但这看起来很乱,而且我不确定它是在什么时候定义的 运行 - 是否总是 运行 立即施工?
谢谢。
好问题!
传递给 promise 构造函数的解析器有意同步运行以支持此用例:
var deferreds = [];
var p = new Promise(function(resolve, reject){
deferreds.push({resolve: resolve, reject: reject});
});
然后,在稍后的某个时间点:
deferreds[0].resolve("Hello"); // resolve the promise with "Hello"
给出promise构造函数的原因是:
- 通常(但不总是)解析逻辑绑定到创建。
- promise 构造函数是抛出安全的并将异常转换为拒绝。
有时它不适合,因此解析器同步运行。 。
更全面的方法如何?
您可以编写一个 returns 一个用 .resolve()
和 .reject()
方法修饰的新 Promise 的构造函数。
您可能会选择将构造函数命名为 Deferred
- 在 javascript 承诺的 [历史] 中具有很多优先级的术语。
function Deferred(fn) {
fn = fn || function(){};
var resolve_, reject_;
var promise = new Promise(function(resolve, reject) {
resolve_ = resolve;
reject_ = reject;
fn(resolve, reject);
});
promise.resolve = function(val) {
(val === undefined) ? resolve_() : resolve_(val);
return promise;//for chainability
}
promise.reject = function(reason) {
(reason === undefined) ? reject_() : reject_(reason);
return promise;//for chainability
}
promise.promise = function() {
return promise.then(); //to derive an undecorated promise (expensive but simple).
}
return promise;
}
通过返回装饰的 promsie 而不是普通对象,除了装饰之外,所有 promise 的自然 methods/properties 仍然可用。
此外,通过处理 fn
,如果您 need/choose 在 Deferred 上使用它,揭示者模式仍然可用。
现在,有了 Deferred()
实用程序,您的代码实际上与 jQuery 示例相同。
var deferreds = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return deferreds[key].promise();
}
var def = Deferred();
deferreds[key] = def;
return def.promise();
}
我想在这里加上我的 2 美分。考虑到问题“Creating a es6 Promise without starting resolve it”我解决了它创建一个包装函数并改为调用包装函数。代码:
假设我们有一个函数 f
,它 return 是一个 Promise
/** @return Promise<any> */
function f(args) {
return new Promise(....)
}
// calling f()
f('hello', 42).then((response) => { ... })
现在,我想准备调用f('hello', 42)
而不实际解决它:
const task = () => f('hello', 42) // not calling it actually
// later
task().then((response) => { ... })
希望这会对某人有所帮助:)
如果我想准备,请按照评论中的要求引用Promise.all()
(并由@Joe Frambach 回答)调用 f1('super')
和 f2('rainbow')
,return 承诺
的 2 个函数
const f1 = args => new Promise( ... )
const f2 = args => new Promise( ... )
const tasks = [
() => f1('super'),
() => f2('rainbow')
]
// later
Promise.all(tasks.map(t => t()))
.then(resolvedValues => { ... })
JavaScript 土地上的情况正在慢慢好转,但这是一个情况,事情仍然不必要地复杂。这是一个简单的助手来公开解析和拒绝函数:
Promise.unwrapped = () => {
let resolve, reject, promise = new Promise((_resolve, _reject) => {
resolve = _resolve, reject = _reject
})
promise.resolve = resolve, promise.reject = reject
return promise
}
// a contrived example
let p = Promise.unwrapped()
p.then(v => alert(v))
p.resolve('test')
显然曾经有一个 Promise.defer
助手,但即便如此,它也坚持将延迟对象与承诺本身分开......
让这类问题看起来复杂的原因是 Javascript 我猜的程序性质。为了解决这个问题,我创建了一个简单的 class。外观如下:
class PendingPromise {
constructor(args) {
this.args = args;
}
execute() {
return new Promise(this.args);
}
}
这个承诺只会在你调用execute()
时执行。例如:
function log() {
return new PendingPromise((res, rej) => {
console.log("Hello, World!");
});
}
log().execute();
CPomise allows you to resolve your promises outside, but this is an antipattern since it breaks Promise incapsulation model. (Live demo)
import CPromise from "c-promise2";
const promise = new CPromise(() => {});
promise.then((value) => console.log(`Done: ${value}`)); //123
setTimeout(() => promise.resolve(123));
使用 ES6 承诺,如何在不定义解析逻辑的情况下创建承诺?这是一个基本示例(一些 TypeScript):
var promises = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return promises[key];
}
var promise = new Promise(resolve => {
// But I don't want to try resolving anything here :(
});
promises[key] = promise;
return promise;
}
function resolveWith(key: string, value: any): void {
promises[key].resolve(value); // Not valid :(
}
使用其他 promise 库可以轻松完成。 JQuery例如:
var deferreds = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return deferreds[key].promise();
}
var def = $.Deferred();
deferreds[key] = def;
return def.promise();
}
function resolveWith(key: string, value: any): void {
deferreds[key].resolve(value);
}
我能看到的唯一方法是将 resolve 函数存储在 promise 的执行程序中的某个地方,但这看起来很乱,而且我不确定它是在什么时候定义的 运行 - 是否总是 运行 立即施工?
谢谢。
好问题!
传递给 promise 构造函数的解析器有意同步运行以支持此用例:
var deferreds = [];
var p = new Promise(function(resolve, reject){
deferreds.push({resolve: resolve, reject: reject});
});
然后,在稍后的某个时间点:
deferreds[0].resolve("Hello"); // resolve the promise with "Hello"
给出promise构造函数的原因是:
- 通常(但不总是)解析逻辑绑定到创建。
- promise 构造函数是抛出安全的并将异常转换为拒绝。
有时它不适合,因此解析器同步运行。
更全面的方法如何?
您可以编写一个 returns 一个用 .resolve()
和 .reject()
方法修饰的新 Promise 的构造函数。
您可能会选择将构造函数命名为 Deferred
- 在 javascript 承诺的 [历史] 中具有很多优先级的术语。
function Deferred(fn) {
fn = fn || function(){};
var resolve_, reject_;
var promise = new Promise(function(resolve, reject) {
resolve_ = resolve;
reject_ = reject;
fn(resolve, reject);
});
promise.resolve = function(val) {
(val === undefined) ? resolve_() : resolve_(val);
return promise;//for chainability
}
promise.reject = function(reason) {
(reason === undefined) ? reject_() : reject_(reason);
return promise;//for chainability
}
promise.promise = function() {
return promise.then(); //to derive an undecorated promise (expensive but simple).
}
return promise;
}
通过返回装饰的 promsie 而不是普通对象,除了装饰之外,所有 promise 的自然 methods/properties 仍然可用。
此外,通过处理 fn
,如果您 need/choose 在 Deferred 上使用它,揭示者模式仍然可用。
现在,有了 Deferred()
实用程序,您的代码实际上与 jQuery 示例相同。
var deferreds = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return deferreds[key].promise();
}
var def = Deferred();
deferreds[key] = def;
return def.promise();
}
我想在这里加上我的 2 美分。考虑到问题“Creating a es6 Promise without starting resolve it”我解决了它创建一个包装函数并改为调用包装函数。代码:
假设我们有一个函数 f
,它 return 是一个 Promise
/** @return Promise<any> */
function f(args) {
return new Promise(....)
}
// calling f()
f('hello', 42).then((response) => { ... })
现在,我想准备调用f('hello', 42)
而不实际解决它:
const task = () => f('hello', 42) // not calling it actually
// later
task().then((response) => { ... })
希望这会对某人有所帮助:)
如果我想准备,请按照评论中的要求引用Promise.all()
(并由@Joe Frambach 回答)调用 f1('super')
和 f2('rainbow')
,return 承诺
const f1 = args => new Promise( ... )
const f2 = args => new Promise( ... )
const tasks = [
() => f1('super'),
() => f2('rainbow')
]
// later
Promise.all(tasks.map(t => t()))
.then(resolvedValues => { ... })
JavaScript 土地上的情况正在慢慢好转,但这是一个情况,事情仍然不必要地复杂。这是一个简单的助手来公开解析和拒绝函数:
Promise.unwrapped = () => {
let resolve, reject, promise = new Promise((_resolve, _reject) => {
resolve = _resolve, reject = _reject
})
promise.resolve = resolve, promise.reject = reject
return promise
}
// a contrived example
let p = Promise.unwrapped()
p.then(v => alert(v))
p.resolve('test')
显然曾经有一个 Promise.defer
助手,但即便如此,它也坚持将延迟对象与承诺本身分开......
让这类问题看起来复杂的原因是 Javascript 我猜的程序性质。为了解决这个问题,我创建了一个简单的 class。外观如下:
class PendingPromise {
constructor(args) {
this.args = args;
}
execute() {
return new Promise(this.args);
}
}
这个承诺只会在你调用execute()
时执行。例如:
function log() {
return new PendingPromise((res, rej) => {
console.log("Hello, World!");
});
}
log().execute();
CPomise allows you to resolve your promises outside, but this is an antipattern since it breaks Promise incapsulation model. (Live demo)
import CPromise from "c-promise2";
const promise = new CPromise(() => {});
promise.then((value) => console.log(`Done: ${value}`)); //123
setTimeout(() => promise.resolve(123));