javascript – 使用异步方法保持对象可链接
作者:互联网
假设我有一个类测试,大约有10-20种方法,所有这些方法都是可链接的.
在另一种方法中,我有一些异步工作要做.
let test = new Test();
console.log(test.something()); // Test
console.log(test.asynch()); // undefined since the async code isn't done yet
console.log(test.asynch().something()); // ERROR > My goal is to make this
由于每个其他方法都是可链接的,我觉得如果这个唯一的方法不是,那对用户来说会很奇怪.
有没有办法让我保持我班级的可连锁主题?
我已经考虑过在这个方法的参数中的回调函数中传递下一个方法,但它并没有真正链接.
test.asynch(() => something())
Promises也是如此,它并不是真正的链接.
test.asynch().then(() => something())
我想要的结果是
test.asynch().something()
这是一个演示我的问题的片段:
class Test {
/**
* Executes some async code
* @returns {Test} The current {@link Test}
*/
asynch() {
if (true) { //Condition isn't important
setTimeout(() => { //Some async stuff
return this;
}, 500);
} else {
// ...
return this;
}
}
/**
* Executes some code
* @returns {Test} The current {@link Test}
*/
something() {
// ...
return this
}
}
let test = new Test();
console.log(test.something()); // Test
console.log(test.asynch()); // undefined
console.log(test.asynch().something()); // ERROR > My goal is to make this work.
解决方法:
我认为做这样的事情是个好主意.
但是如果原始对象满足某些条件,则使用Proxy将允许创建这样的beahviour.我强烈建议不要这样做.
请注意,此代码是一个概念证明,表明它在某种程度上是可能的,但不关心边缘情况,并且很可能会破坏某些功能.
一个代理用于包装原始类Test,以便可以修补每个实例以使它们可链接.
第二个将修补每个函数调用并为这些函数调用创建一个队列,以便按顺序调用它们.
class Test {
/**
* Executes some async code
* @returns {Test} The current {@link Test}
*/
asynch() {
console.log('asynch')
return new Promise((resolve, reject) => setTimeout(resolve, 1000))
}
/**
* Executes some code
* @returns {Test} The current {@link Test}
*/
something() {
console.log('something')
return this
}
}
var TestChainable = new Proxy(Test, {
construct(target, args) {
return new Proxy(new target(...args), {
// a promise used for chaining
pendingPromise: Promise.resolve(),
get(target, key, receiver) {
// intercept each get on the object
if (key === 'then' || key === 'catch') {
// if then/catch is requested, return the chaining promise
return (...args2) => {
return this.pendingPromise[key](...args2)
}
} else if (target[key] instanceof Function) {
// otherwise chain with the "chainingPromise"
// and call the original function as soon
// as the previous call finished
return (...args2) => {
this.pendingPromise = this.pendingPromise.then(() => {
target[key](...args2)
})
console.log('calling ', key)
// return the proxy so that chaining can continue
return receiver
}
} else {
// if it is not a function then just return it
return target[key]
}
}
})
}
});
var t = new TestChainable
t.asynch()
.something()
.asynch()
.asynch()
.then(() => {
console.log('all calles are finished')
})
标签:javascript,asynchronous,method-chaining 来源: https://codeday.me/bug/20190607/1194335.html