我正在研究react native中的一些特定用例,我希望在不干扰运行react nativeUI和动画的主线程的情况下执行一些繁重的JS操作。
例如,一旦安装应用程序组件或用户触发任何动画序列(例如,导航到新视图动画、打开一些详细信息页面动画等(,就运行for循环10K次。
如果我在动画开始前执行以下代码,
// animate the item details page (from item list page)
onItemPressed() {
// Some JS code to mimic heavy processing
console.log('starting...');
for (let i = 0; i < 5000; i++) {
(Math.random() * 9999999) / 7;
}
console.log('Finished');
// starting animation sequence
this.setState({animationPhase: 'phase-2'});
}
在直接运行上面的代码之后,由于在动画开始之前运行的代码,动画是滞后的。
我正在研究以下方法:
使用RN的InteractionManager-阅读文档后,可以按照文档中提到的那样实现它-在InteractionManager.runAfterInteractions((处理程序中包装for循环。然而,这并不能完全解决问题。它下面还有另一个方法,名为setDeadline,它的文档很少。我认为它对处理大块数据很有用,而不是一次处理整个代码。不知道如何使用。
RequestAnimationFrame/SetTimeout-未按预期工作
React原生线程/工作者-像API这样的Web工作者在后台处理任务。这可以正常工作,还有一个额外的优势,即我们可以向工作线程发送/侦听消息,以启动/停止任务执行。根据RNThreads的文档,我们可以将其用作-
import { Thread } from 'react-native-threads'; // import it in the required component this.thread = new Thread('./JS_FILE_THAT_HAS_HEAVY_DUTY_CODE.js'); // create new instance of it this.thread.onmessage = (message) => {} // listen to messages coming from the JS file this.thread.postMessage('Start'); // post message to the thread componentWillUnmount() { // stop the JS process this.thread.terminate(); } // In thread.js file, import { self } from 'react-native-threads'; // import current worker context obj self.onmessage = message => { // Listen to messages coming from parent script // start execution } self.postMessage('Completed'); // post messages to parent script
使用WebView-我还没有尝试过,但这篇文章在这种情况下似乎很有用,但将字符串化的javascript注入到web视图中可以吗?不确定。
我的问题是-
- 我想了解更多关于RN交互管理器的信息,尤其是setDeadline((方法-如何使用它以及它的作用
- 在这种用例中,哪种方法更好
我没有一个确切的答案,因为我对InteractionManager.setDeadline()
也不太熟悉,但我认为查看测试可以提供您想要的见解。通常,测试可以很好地替代文档的缺乏。
因此,请查看InteractionManager-test.js,特别是L230-L261
在那里,你会发现这些测试。。。
it('should execute tasks in loop within deadline', () => {
InteractionManager.setDeadline(100);
BatchedBridge.getEventLoopRunningTime.mockReturnValue(10);
const task1 = createSequenceTask(1);
const task2 = createSequenceTask(2);
InteractionManager.runAfterInteractions(task1);
InteractionManager.runAfterInteractions(task2);
jest.runOnlyPendingTimers();
expectToBeCalledOnce(task1);
expectToBeCalledOnce(task2);
});
it('should execute tasks one at a time if deadline exceeded', () => {
InteractionManager.setDeadline(100);
BatchedBridge.getEventLoopRunningTime.mockReturnValue(200);
const task1 = createSequenceTask(1);
const task2 = createSequenceTask(2);
InteractionManager.runAfterInteractions(task1);
InteractionManager.runAfterInteractions(task2);
jest.runOnlyPendingTimers();
expectToBeCalledOnce(task1);
expect(task2).not.toBeCalled();
jest.runOnlyPendingTimers(); // resolve1
jest.runOnlyPendingTimers(); // task2
expectToBeCalledOnce(task2);
});
在我看来,这是一种分配工作的方式,可能很有用。
您的解决方案3。很有趣。我个人很想看到一些代码。我在这方面没有经验,但这听起来很令人兴奋。我认为webview肯定有助于将工作卸载到一个单独的线程,但我以前从未在这种情况下使用过它。