2

我可以订阅这样的商店:

count.subscribe(value => {
  count_value = value;
});

但是当我们想取消订阅时,我们会将之前的订阅代码放入一个新变量中(成为一个函数表达式),并且只有在组件被销毁时才运行它(onDestroy

const unsubscribe = count.subscribe(value => {
    count_value = value;
});

onDestroy(unsubscribe);

问题是,如何将前一个函数放入一个名为 unsubscribe 的新变量中。可以对商店执行取消订阅功能。我的意思是我们甚至根本不改变取消订阅实现的订阅代码,我们所做的只是把它放在一个新的变量中,让它变成一个函数表达式并且只通过 调用它onDestroy,那么它怎么能神奇地取消订阅呢?它实际上是如何工作的?

4

2 回答 2

3

subscribe不返回您作为参数传递的函数:它返回一个实现取消订阅行为的新函数。


如果您查看自定义商店合同的 Svelte 文档(已添加重点),这将更容易理解:

店铺合同

store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void }

通过实现 store 契约,你可以创建自己的 store 而不依赖于svelte/store

  1. 商店必须包含一个.subscribe方法,该方法必须接受订阅函数作为其参数。此订阅函数必须在调用 .subscribe 时立即与商店的当前值同步调用。每当商店的价值发生变化时,商店的所有活动订阅函数都必须在以后同步调用。
  2. .subscribe方法必须返回一个取消订阅函数。调用取消订阅函数必须停止其订阅,并且商店不能再次调用其对应的订阅函数。

如果您想进一步证明 的返回值与subscribe您传递的函数不同,只需提取 的类型store.subscribe

Type subscribe = (subscription: (value: any) => void) => (() => void)

subscription参数的(value: any) => void签名 与返回值的签名不匹配() => void


这是商店合约的简单实现,演示了如何构建取消订阅功能。

class Store {
    constructor(init) {
        this.subscribers = {};
        this.value = init;
    }
    subscribe(callback) {
        callback(this.value);
        const id = Symbol()
        this.subscribers[id] = callback;

        return () => delete this.subscribers[id]
        //     ^^^ unsubscribe function here ^^^

    }
    set(value) {
        this.value = value;
        for (const id of Object.getOwnPropertySymbols(this.subscribers)) {
            this.subscribers[id](value)
        }
    }
}
于 2021-07-02T18:42:02.323 回答
2

但是当我们想取消订阅时,我们会将之前的订阅代码放入一个新变量中

这不是这里发生的事情。该函数未分配给unsubscribe变量;它的返回值是另一个函数。

想象一下subscribe是这样的:

const subscribe = (callback) => {
  callback('the stored value')

  const unsubscribe = () => {
    // do all the stuffs to unsubscribe here...
    console.log('Your are unsubscribed!')
  }

  return unsubscribe
}

let count_value

// unsubscribe is now the function returned in the subscribe function
const unsubscribe = subscribe(value => {
  count_value = value;
})

console.log(count_value)

// calling this function will log 'You are unsubscribed!' in the console
unsubscribe()

于 2021-07-02T13:38:37.860 回答