gpt4 book ai didi

redux - 替代直接调用 store.dispatch()

转载 作者:行者123 更新时间:2023-12-04 09:12:06 26 4
gpt4 key购买 nike

由于在最新的 redux-observable (0.17) 中直接调用 store.dispatch() 已弃用,我想知道如果我需要从我的 redux 应用程序外部调度操作,还有什么替代方案。

例子:

假设我有这个函数来初始化 native 模块并设置 native 处理程序。

const configure = (dispatch) => {
const printingModule = NativeModules.PrintingManager
const eventEmitter = new NativeEventEmitter(printingModule)

eventEmitter.addListener(
"PrintingManagerNewPrinterConnected",
(payload) => dispatch({
type: PRINTER_MANAGER_NEW_PRINTER_CONNECTED,
payload: {
macAddress: payload[2],
connectionType: payload[3],
},
}))

printingModule.initialize()
}

我通常会在 APP_STARTUP_FINISHED 之后从 observable 调用这个函数:
const appStatePrepared = (action$: Object, { dispatch }) =>
action$.ofType(APP_STATE_PREPARED)
.switchMap(() => {
configurePrinters(dispatch)
})

什么是正确的解决方案?

谢谢!

最佳答案

使用 RxJS 时,理想的是组合流。因此,在这种情况下,我们需要了解如何创建 "PrintingManagerNewPrinterConnected" 的流。然后我们可以将每个事件映射到它们自己的 PRINTER_MANAGER_NEW_PRINTER_CONNECTED行动.a

让我们首先学习如何完全自定义。

自定义 Observables

创建自己的自定义 Observable 与创建 Promise 非常相似。所以假设你有世界上最简单的 Promise,它立即解析为数字 1

const items = new Promise(resolve => {
resolve(1);
});

等效的 Observable 看起来 super 相似

const items = new Observable(observer => {
observer.next(1);
observer.complete();
});

从视觉上看,主要区别在于不是通过 (resolve, reject)回调我们被赋予了一个观察者,因为有下一个,错误和完成。

从语义上讲,Observable 可以通过调用 observer.next 来表示多个值。在他们调用 observer.complete() 之前,他们想多少次都可以。表示流的结束;这与仅代表单个值的 Promises 形成对比。

默认情况下,Observables 也是惰性和同步的,而 Promise 总是渴望和异步的。

既然我们有了这种理解,我们想把它包装起来你的 NativeEventEmitter使用 addEventListener 的 API .

const configurePrinters = () => {
return new Observable(observer => {
const printingModule = NativeModules.PrintingManager;
const eventEmitter = new NativeEventEmitter(printingModule);

eventEmitter.addListener(
'PrintingManagerNewPrinterConnected',
(payload) => observer.next(payload)
);

printingModule.initialize();
});
};

configurePrinters()
.subscribe(payload => console.log(payload));

这很有效,而且非常简单,但有一个问题:我们应该调用 removeListener当他们取消订阅以便我们自己清理并且不泄漏内存时。

为此,我们需要在自定义的 Observable 中返回订阅。此上下文中的订阅是具有 unsubscribe() 的对象。方法,当订阅者取消订阅、触发错误或您的 observable 完成时,将自动调用该方法。这是你清理的机会。

const items = new Observable(observer => {
let i = 0;
const timer = setInterval(() => {
observer.next(i++);
}, 1000);

// return a subscription that has our timer cleanup logic
return {
unsubscribe: () => {
clearInterval(timer);
}
};
});

因为返回一个对象有点冗长,RxJS 支持一个简写,你只返回一个函数,它本身将被视为 unsubscribe方法。

const items = new Observable(observer => {
let i = 0;
const timer = setInterval(() => {
observer.next(i++);
}, 1000);

// return an "unsubscribe" function that has our timer cleanup logic
return () => {
clearInterval(timer);
};
});

现在我们可以将它应用到我们的示例中,我们希望在调用取消订阅拆卸函数时删除我们的监听器。

const configurePrinters = () => {
return new Observable(observer => {
const printingModule = NativeModules.PrintingManager;
const eventEmitter = new NativeEventEmitter(printingModule);

const listener = (payload) => observer.next(payload);

eventEmitter.addListener(
'PrintingManagerNewPrinterConnected',
listener
);

printingModule.initialize();

return () => eventEmitter.removeListener(
'PrintingManagerNewPrinterConnected',
listener
);
});
};

现在让我们把它变成一个可重用的实用函数

const fromPrinterEvent = (eventName) => {
return new Observable(observer => {
const printingModule = NativeModules.PrintingManager;
const eventEmitter = new NativeEventEmitter(printingModule);

const listener = (payload) => observer.next(payload);
eventEmitter.addListener(eventName, listener);
printingModule.initialize();

return () => eventEmitter.removeListener(eventName, listener);
});
};

fromPrinterEvent('PrintingManagerNewPrinterConnected')
.subscribe(payload => console.log(payload));

Observable.fromEvent

NativeEventEmitter是一个 react 原生的东西,它遵循 node-style EventEmitter interface并且 RxJS 已经附带了一个实用程序助手来从它们创建一个 Observable 以节省您的工作量。 It's called fromEvent , 发现于 Observable.fromEventimport { fromEvent } from 'rxjs/observables/fromEvent' .

const fromPrinterEvent = (eventName) => {
return Observable.defer(() => {
const printingModule = NativeModules.PrintingManager;
const eventEmitter = new NativeEventEmitter(printingModule);
printingModule.initialize();

return Observable.fromEvent(eventEmitter, eventName);
});
};

这里我也把它包裹在 Observable.defer 这样我们就不会创建 NativeEventEmitterprintingModule.initialize()直到有人真正订阅(保持懒惰)。这对您来说可能是也可能不是,我不知道 PrintingManager 的作用或行为方式。例如最好只创建一个发射器并预先初始化模块。

const printingModule = NativeModules.PrintingManager;
const printerEmitter = new NativeEventEmitter(printingModule);
printingModule.initialize();

const fromPrinterEvent = (eventName) =>
Observable.fromEvent(printerEmitter, eventName);

所以请记住,我只是在显示模式而不知道 PrintingManager 等的作用。

在 redux-observable 中使用它

要在 redux-observable 中使用它,并且您的史诗现在与使用任何其他 Observable 相同。所以我们想要将它的值映射到 Action 和
将它们合并到我们的顶级流中。

像这样的东西:

const appStatePrepared = action$ =>
action$.ofType(APP_STATE_PREPARED)
.switchMap(() =>
fromPrinterEvent('PrintingManagerNewPrinterConnected')
.map(payload => ({
type: PRINTER_MANAGER_NEW_PRINTER_CONNECTED,
payload: {
macAddress: payload[2],
connectionType: payload[3],
}
}))
);

请记住,许多流,包括我们的自定义 fromPrinterEvent('PrintingManagerNewPrinterConnected') ,直到您取消订阅它们为止。所以如果你只想要一个,你会使用 .take(1) .如果您想在收到其他操作时取消订阅,您可以使用 .takeUntil(action$.ofType(WHATEVER))等。 正常的 RxJS 模式。

关于redux - 替代直接调用 store.dispatch(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47665255/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com