【问题标题】:Wrap a function with an Observable to create a hot listener用 Observable 包装一个函数来创建一个热监听器
【发布时间】:2021-04-29 07:03:44
【问题描述】:

手头有几件事:

这将是冗长而准确的,因为我真的很想弄清楚我的问题

我已阅读 RXJS 文档 我看过这个Wrap an API function in an RxJs Observable 帖子。 我看过其他几个帖子。 不幸的是,没有人帮助我。

我正在使用 Vue 2.6 编写

我创建了一个包装器,以便在我的 Vue 应用程序中轻松管理 RXJS 我已经在我的应用程序中将 RXJS 实例实例化为单调对象

Vue.prototype.$rx = Rxjs;

我还在我的 VUEX 中存储了我的 RXJS 的这个实例

store.commit('setProperty', {key: 'rx', value: Vue.prototype.$rx})

这样我就可以在我的 VUEX 商店中使用 RXJS

我的 RXJS 对象只是一个包装器

export const Rxjs = {
    create(namespace, subjectType = 'subject') {
        this[namespace] = new RxjsInstance(subjectType)
    }
}

它根据我的 VUEX 命名空间模块为我的应用程序中的每个命名空间实例化一个新的 RXJS 类

所以对于“主页”屏幕,我有一个主页 VUEX 模块和一个 RXJS(如果需要 - 它们不会自动实例化)实例来保存主页的订阅 基于这个类:

export class RxjsInstance {
    constructor(subjectType) {
        this.subscriptions = new Subscription();
        switch (subjectType) {
            case 'subject':
                this.subject = new Subject();
                break;
            case 'asyncSubject':
                this.subject = new AsyncSubject();
                break;
            case 'behaviorSubject':
                this.subject = new BehaviorSubject(null);
                break;
            case 'replaySubject':
                this.subject = new ReplaySubject();
                break;
        }
    }

    next(data) {
        this.subject.next(data);
    }

    asObservable() {
        return this.subject.asObservable();
    }

    set add(subscription) {
        this.subscriptions.add(subscription);
    }

    subscribe(subscriber, callback) {
        if (!subscriber) {
            throw 'Failed to subscribe. Please provide a subscriber'
        }
        subscriber = this.asObservable().subscribe(data => {
            callback(data)
        });
        this.subscriptions.add(subscriber)
    }

    unsubscribe() {
        this.subscriptions.unsubscribe();
    }
}

简而言之 - 这个类实际上返回了一个准系统 RXJS 功能,其附加价值是让订阅自动保存在实例的本地数组中,以便更轻松地控制和防止内存泄漏 - 没什么特别的 - 只是为了简化我的团队。

因此,就目前而言,我有一个 gloal RXJS 对象,它位于我的应用程序的任何地方——我可以从每个组件访问它,并允许我将数据从 A 点传输到 B 点,而无需使用多个“道具”和父组件和子组件之间的发射量相等。 所有这一切都没有触及我的 VUEX 状态(与 Redux 不同,它不是不可变的) 所以当我改变我的状态时——它的数据是干净且受控的。

现在解决我的问题。

我正在尝试找出一种方法来使用 RXJS 将现有函数与 observable 一起包装,以便在调用该函数时可以订阅它。

假设我有一个 alertUser(msg) 函数,它只是将 'msg' arg 附加到一个

我的 DOM 中的元素。

我想“订阅”这个函数 - 根本不改变它!通过用 observable 包装它或为其分配一个。 我不确定这是否可行——因为我所看到的 RXJS 所做的只是创建一个执行该功能的可观察对象,然后对其进行替换。 但是因为我正在将 RXJS 集成到一个已经存在的应用程序中 - 我无法将所有内容都重构为 observable。

所以我的最终目标是

alertUser(msg){
    this.appendToPElement(msg)
}

this.localVariable = ObservThatFunction(){
\\ this is where I want the magic to happen and listen to the alertMsg func and make this an observable i can subscribe to
}

this.sub = this.localvariable.subscribe(data=>{console.log(data)})

这可能吗?

编辑: observable 不必传递函数的数据 - 只需在调用函数时发出一个值(甚至是 bool 值)

例如,当 this.alertUser() 被调用时,我希望调用 observable - 我的订阅者现在可以更新通知服务,通知服务已经发送了新的 msg - 无论该消息是什么

【问题讨论】:

  • 订阅时你的 observable 应该发出什么? this.localvariable.subscribe(data=>{console.log(data)}) 中的 data 是什么?
  • observable 会发出它可以发出的信号——它甚至可以发出“真”,这样我就知道该函数被调用了。就像在不写回调的情况下对其进行回调一样。所以 DATA 并不重要 - 它可以只是一个字符串或 w/e 我只想知道函数何时被调用,这样我就可以对它做出反应而不用回调来改变它所以现在我可以让 observable 告诉我它被调用并更新我的通知服务,例如@lbsn

标签: javascript vue.js vuejs2 rxjs vuex


【解决方案1】:

TL;DR:这根本不可能。

简而言之,您想窥探特定方法。在 JavaScript 中可靠 spy/stub 的唯一方法是使用ES Proxy。但是代理就像一个方法的包装器。如果此函数是您要导出的对象的一部分,那么 Proxy 会起作用。但事实并非如此。此外,您需要调用 代理 函数,而不是直接调用原始函数。另一种方法是使用 JavaScript [装饰器][2],但它们还不是标准的,仅在类/方法上下文中有用。

但是,作为一种解决方法,您可以在不更改语义并将其包装成 observable 的情况下修改函数。这个想法是创建一个全局主题并从alertUser()调用它:

window.messageQueue = new Subject();

alertUser(msg){
  this.appendToPElement(msg);

  // This is non-destructive.
  window.messageQueue.next(msg);
}

// Usage
window.messageQueue.subscribe(() => { /* next */});

【讨论】:

  • 首先,谢谢 :) 这是我已经做过的事情 - 这就是为什么我为每个命名空间实例化一个 rx js 以便我可以在我的应用程序的任何地方访问该命名空间,是的,我可以在现有函数中“种植”代码行 :) 你验证了我的思考过程。非常感谢 :)
【解决方案2】:

这里只是猜测,但Proxy 可能会有所帮助。

    const handler = {
      apply: function(target, thisArg, argumentsList) {
        obs.next(true);
        return target(argumentsList);
      }
    };

   function observeFn(fn) {
     return new Proxy(fn, handler);
   }

然后你可以像这样包装你的原始函数:observeFn(alertUser)obs 应该通知对该函数的任何调用。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-17
  • 2021-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多