使用异步方法保持对象可链接 [英] Keep object chainable using async methods

查看:64
本文介绍了使用异步方法保持对象可链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有一个Test类,其中包含约10-20个方法,所有这些方法都是可链接的.

Let's say I have a class Test with around 10-20 methods, all of which are chainable.

在另一种方法中,我要做一些异步工作.

In another method, I have some asynchronous work to do.

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 

由于其他所有方法都是可链接的,因此,如果不是这种唯一的方法,我觉得这对于用户来说很奇怪.

Since every other method is chainable, I feel like it would be weird for the user if this sole method isn't.

我是否可以维持班级可链接的主题?

Is there a way for me to maintain the chainable theme of my Class?

我已经考虑过在该方法的参数内部的回调函数中传递下一个方法,但这并不是真正链接.

I have already thought of passing the next method in a callback function inside this method's parameter, but it's not really chaining.

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.

推荐答案

我怀疑做这样的事情真的是个好主意. 但是,使用代理可以创建如果原始Object满足某些条件,则为此类行为.我强烈建议您不要那样做.

I doupt that it is a really good idea to do something like that. But using a Proxy would allow to create such a beahviour if the original Object meets certain conditions. And I would highly recommend to not do it that way.

请注意,此代码是概念证明,表明它在某种程度上是可能的,但并不在乎边缘情况,并且很可能会破坏某些功能.

Be aware that this code is a proof of concept to show that it is somehow possible, but doesn't care about edge cases and most likely will break certains functionalities.

使用一个代理包装原始类Test,以便可以修补每个isins实例以使其可链接.

One Proxy is used to wrap the original class Test so that is is possible to patch each of is instance to make them chainable.

第二个将修补每个函数调用并为这些函数调用创建一个队列,以便依次调用它们.

The second one will patch each function call and creates a queue, for these functions calls so that they are called in order.

    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')
      })

这篇关于使用异步方法保持对象可链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆