我正在研究 React Native 中的一些特定用例,我希望在不干扰在 React Native 中运行 UI 和动画的主线程的情况下执行一些繁重的 JS 操作。
示例是,一旦应用程序组件安装或用户触发任何动画序列(例如导航到新 View 动画、打开一些详细信息页面动画等),就运行 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 - 阅读文档后,可以按照文档中提到的方式实现它 - 将 for 循环包装在 InteractionManager.runAfterInteractions() 处理程序中。然而,这并不能完全解决问题。它下面还有另一种方法,称为setDeadline,该方法的记录很少。我认为它对于处理数据 block 很有用,而不是一次处理整个代码。不知道如何使用它。
RequestAnimationFrame/SetTimeout - 未按预期工作
React native 线程/工作线程 - Web Workers 喜欢 API 在后台处理任务。这可以正常工作,并具有额外的优点,即我们可以向工作线程发送/监听消息以启动/停止任务执行。根据 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 - 我还没有尝试过,但是this post在这种情况下似乎很有用,但是将字符串化的 javascript 注入(inject)到 Web View 中可以吗?没有把握。
我的问题是 -
- 我想了解有关 RN Interaction Manager 的更多信息,尤其是 setDeadline() 方法 - 如何使用它以及它的作用。
- 在此类用例中哪种方法更好?
最佳答案
我没有给你一个可靠的答案,因为我对 InteractionManager.setDeadline() 也不太熟悉,但我认为查看测试可以为你提供见解。重新之后。通常,测试可以很好地替代文档的缺乏。
因此,请查看 InteractionManager-test.js, specifically 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 绝对应该有助于将工作卸载到单独的线程,但我以前从未在这种情况下使用过它。
关于javascript - React Native - 处理繁重的 JS 代码而不影响性能/渲染的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53805122/