链接承诺而不使用“then”
Chaining promises without using 'then'
我有一个对象(foo
),它将几个方法公开为承诺(使用jQuery deferred)。我这样做的方式最终得到了这种代码:
var foo = createNewFoo();
$.when(foo.method1(arg))
.then(foo.method2)
.then(foo.method3);
我希望重构下面的代码更好,看起来像这样:
var foo = createNewFoo()
.method1(arg)
.method2()
.method3();
但我不确定如何实现foo
这是可能的。
是的,当然,您只需要扩展Deferred
即可使用这些方法:
function MyRpc { // if you can use ES2015 - this should be a `class`
this._deferred = new $.Deferred();
}
// teach it to be a promise
MyRpc.prototype.then = function(onFulfilled, onRejected) {
return this._deferred.then(onFulfilled, onRejected);
};
// teach it to be a deferred
MyRpc.protototype.resolve = function(arg) {
this._deferred.resolve(arg);
};
MyRpc.prototype.reject = function(arg) {
this._deferred.reject(arg);
};
// define your methods!
MyRpc.prototype.method1 = function(arg) {
var p = this._deferred.then(function(value) {
// logic of `method1` from foo.method1 here
});
var rpc = new MyRpc(); // our continuation;
p.then(function(v) { rpc.resolve(v) }, function(e) { rpc.reject(e); });
return rpc;
};
当然,使用真正的 promise 库,这一切都比使用 jQuery 的最小 promise 要容易得多。
这将允许您执行以下操作:
var rpc = new MyRpc();
rpc.method1(1).method1(2).method1(3); // can also `.then` here
我不确定这是否值得,但它有效。
您需要返回一个包含所需方法的自定义对象,并让它直接将状态而不是状态作为属性。在每个方法中,都需要对包装的承诺调用then
,并返回另一个实例,该实例为新状态(方法结果)包装新承诺。
function Foo(promise) {
// make every instance a thenable:
this.then = promise.then.bind(promise);
// alternatively store the promise itself as a property and always call this.promise.then
}
function createNewFoo() {
return new Foo($.when({/* initial state */}));
}
Foo.prototype.method1 = function method1(args) {
return new Foo(this.then(function(curstate) {
// method logic here
// should `return` a new state - or a promise for it
});
};
Foo.prototype.method2 = …;
这类似于Benjamin Gruenbaum和Louy概述的方法,但实现起来要简单得多。
我真的不知道承诺(所以如果有一些实现错误,请原谅我的例子),但这可以使用 ES6 Proxy
.
目前,它仅在最新的浏览器上可用,因此可能无法满足您的要求。
代理允许在每个对象操作上添加一个回调函数,这意味着您可以检索被调用方法的名称来执行您想要的操作。在您的情况下,您希望使用第一个 promise 调用 $.when()
,并使用其他人调用 .then()
作为参数。
"use strict";
function createNewFoo(){
let foo = new Foo();
let proxy = new Proxy(foo, {
// @param target : Object on which the operation will be made
// @param name : property name
get(target, name) {
let promise = target[name];
return function (...args) {
if (typeof promise === "function"){
promise = promise.apply(target, args);
}
else if (!(promise instanceof Promise)){
throw 'Can''t handle "'+name+'"';
}
// Perform chaining
if (!target.promise){
target.promise = $.when(promise);
}
else{
target.promise.then(promise);
}
return proxy;
};
}
});
// Storing the Foo instance in the Proxy object, could be implemented in other way.
proxy._target = foo;
return proxy;
}
假设您使用的是定义为波纹管的"类"
function Foo(){
// storing the promise result
this.promise = null;
this.method1 = function(arg){
return new Promise(function(resolve, reject) {
resolve("1");
});
}
this.method2 = new Promise(function(resolve, reject) {
resolve("2");
});
this.method3 = new Promise(function(resolve, reject) {
resolve("3");
});
}
您现在可以使用这段代码来链接您的承诺
var fooProxy = createNewFoo()
.method1(1)
.method2()
.method3();
并检索原始 Foo 实例
fooProxy._target
创建自己的承诺。
function MyPromise(resolver) {
var _promise = new Promise(resolver);
this.then = function(onFulfilled, onRejected) {
var _p = _promise.then(onFulfilled, onRejected);
return new MyPromise(_p.then.bind(_p));
};
}
添加您想要的任何方法...
MyPromise.prototype.doSomething = function() {
return this.then(/*...*/);
};
瞧!
new MyPromise()
.then(/*...*/).doSomething()
.then(/*...*/).doSomething(); // etc...
奖金:
['resolve', 'reject', 'all'].forEach(function(method) {
MyPromise[method] = function(...args) {
var promise = Promise[method](...args);
return new MyPromise(promise.then.bind(promise));
};
});
同样在 ES6 中:
class MyPromise {
constructor(resolver) {
var _promise = new Promise(resolver);
this.then = function(onFulfilled, onRejected) {
var _p = _promise.then(onFulfilled, onRejected);
return new MyPromise(_p.then.bind(_p));
};
}
doSomething() {
return this.then(/*...*/);
}
}
相关文章:
- AngularJS因果报应测试规范承诺未解析,且未调用.then()
- 当链接javascript承诺时,如何处理then()函数中的条件
- 角承诺的“then”函数的成功回调的词汇范围是什么?
- “未捕获(在承诺中)”在获取“then”方法中调用拒绝函数时
- 为什么.then()在承诺真正解决之前就被解雇了
- Javascript承诺:then()'s是't同步
- Chain承诺使用then()
- Javascript 承诺 .catch 仍然调用 final variable.then
- 当承诺在监视函数中解析时,如何使承诺的 then 函数起作用
- 链接承诺而不使用“then”
- 问.js节点承诺.“套接字”上缺少错误处理程序.类型错误:无法调用未定义的方法“then”
- 为什么 .then() 不等待承诺
- 咖啡脚本中的承诺.尝试将多个参数传递给“then”时出现“意外逗号”错误
- 在 then() 中断开 for 循环 在一个承诺
- 然后 .then() 函数似乎在承诺完成之前运行
- 用一个参数承诺 .then()
- 与茉莉花中 ES6 承诺的 then/catch 方法同步
- 承诺链接:在next-then回调中使用上一个承诺的结果
- AngularJs的承诺&;then &;承诺之前的火焰已被化解
- 如何重用一个函数,是在一个链之间的then(承诺相关)