admin管理员组

文章数量:1287524

I'm building a new app with React Native and Expo. The main function of this app is to generate plans for user. The generating algorithm will take estimated around 300-500 seconds to execute. (It contains maximum 2,100,000 times of random generating.)

Currently I am facing two problems:

Q1. during testing, this piece of code is put in the App.js - App class - render function directly. however, it seems that if the execution time exceeds 32 seconds the app will just fail to render and stay no response forever.

So the question is:

1.1 what's the reason of the maximum 32 seconds otherwise no response?

1.2 are there better ways to do testing?

Current testing method:

export default class App extends React.Component {
  ponentDidMount() {
    if (__DEV__) {
      Reactotron.connect();
      Reactotron.log('hello rendering world');
    }
  }

  render() {
    //test
    generatePlan(store.getState(), 0);

    return (
      <Provider store={store}>
        <AppContainer />
      </Provider>
    );
  }
}

Q2. at the end, it's not possible to let user keep dazing such a long time after click an "generating" button. So ideally, this long executing task should be running in the background with limited resource (both memory and calculating), so that the user can do other things during waiting without too much being influenced(like a virus scanning task, once it finishes, pops up a message, etc.)

So the question here is:

how to implement this?

What I have tried:

For Q1: currently I have no idea about the reason and even can't figure out the accurate key words to search. (I tried search "react native long execution time", "no response", etc in google, react native github issue, Expo forum, but no luck.)

currently my idea to do testing is to execute each part separately and manually store the result of each part. Then do the final part with the stored result of each part.

For Q2: There is a library "react-native-background-task":

"This library allows the scheduling of a single periodic task, which executes when the app is in the background or closed, no more frequently than every 15 minutes. Network, AsyncStorage etc can be used (anything except UI), so perfect for things like a background data sync for offline support."

But there are two questions about this potential solution:

a. how to run task in the background when the app is open?

b. how to limit the calculating resource used by this task? (as the task can be executed slowly, but it shouldn't occupy too much calculating resource if the user is still using the mobile phone.)

I'm building a new app with React Native and Expo. The main function of this app is to generate plans for user. The generating algorithm will take estimated around 300-500 seconds to execute. (It contains maximum 2,100,000 times of random generating.)

Currently I am facing two problems:

Q1. during testing, this piece of code is put in the App.js - App class - render function directly. however, it seems that if the execution time exceeds 32 seconds the app will just fail to render and stay no response forever.

So the question is:

1.1 what's the reason of the maximum 32 seconds otherwise no response?

1.2 are there better ways to do testing?

Current testing method:

export default class App extends React.Component {
  ponentDidMount() {
    if (__DEV__) {
      Reactotron.connect();
      Reactotron.log('hello rendering world');
    }
  }

  render() {
    //test
    generatePlan(store.getState(), 0);

    return (
      <Provider store={store}>
        <AppContainer />
      </Provider>
    );
  }
}

Q2. at the end, it's not possible to let user keep dazing such a long time after click an "generating" button. So ideally, this long executing task should be running in the background with limited resource (both memory and calculating), so that the user can do other things during waiting without too much being influenced(like a virus scanning task, once it finishes, pops up a message, etc.)

So the question here is:

how to implement this?

What I have tried:

For Q1: currently I have no idea about the reason and even can't figure out the accurate key words to search. (I tried search "react native long execution time", "no response", etc in google, react native github issue, Expo forum, but no luck.)

currently my idea to do testing is to execute each part separately and manually store the result of each part. Then do the final part with the stored result of each part.

For Q2: There is a library "react-native-background-task":

"This library allows the scheduling of a single periodic task, which executes when the app is in the background or closed, no more frequently than every 15 minutes. Network, AsyncStorage etc can be used (anything except UI), so perfect for things like a background data sync for offline support."

But there are two questions about this potential solution:

a. how to run task in the background when the app is open?

b. how to limit the calculating resource used by this task? (as the task can be executed slowly, but it shouldn't occupy too much calculating resource if the user is still using the mobile phone.)

Share Improve this question edited Aug 22, 2019 at 5:32 Chenhua asked Aug 22, 2019 at 5:25 ChenhuaChenhua 2033 silver badges10 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 8

@Heysem Katibi thanks a lot for shedding light on this.

below is my discovery and experience along the way to solve this problem.

  1. the Javascript part of React Native is single thread originally (currently oct,2019) which means any long execution code will block main UI thread directly.
  2. for long execution code, there do be multiple solutions to avoid this blocking problem. However, currently none of them can be achieved with Expo (or without ejecting / detaching).

Solutions in details:

  1. react native Javascript worker: react-native-threads (itself or with hamsters.js to further speed up).

    react-native-threads will spawn new react native JavaScript processes for CPU intensive work outside of the main UI JavaScript process.

    hamsters.js is a Javascript Multithreading & Parallel Execution Library, can further speed up the execution while it needs a worker library with React Native (ex: react-native-threads).

  2. requestAnimationFrame: Break code into pieces and execute in each frame.

    See Intensive JavaScript. This probably can work, however as this article shows, the performance will be worse than worker.

  3. move to native code:

    • Objective-C/Swift for iOS and Java/Kotlin for android
    • C++ for both platform. However, this needs to pile all C++ library used for mobile(which sometimes can be licated, ex: google/or-tools do not provide official mobile piled version neither official guide to do it).
    • Golang for both platform and pile for iOS and Android with golang/mobile. However, Golang does not have a mature ecosystem currently (year 2019). So third party packages can be hard to e by.
    • Besides, there may be some other languages provide bundling for both iOS and android.

    In any cases, moving code to native will probably boost up the execution.

  4. move to server side: use remote server to do the heavy job and the mobile side just request the result. Also, this can work with above solutions (considering using the same language to write the code and reuse on both mobile and server side).

By thankful original poster.

P.S: I just discovered that it's very difficult to encrypt javascript code in React Native project. Thus it's not advised to put any sensitive code in javascript and even in front end.

Well, I don't think there is one definite answer to your question, But here is what I think:

  • I'm not sure about any 32 seconds render limit but blocking the UI for even 1 second is not practical and bad for user experience.
  • It is not a good practice to perform anything inside the render() method. This method is called frequently whenever a piece of the state is updated or the ponent is re-rendered. So it should be as light as possible and should only contain the returned ponents, Also to avoid any unexpected behaviors the render() method should be a pure method related to its ponent's props and state.
  • What I would do in this case is re-writing the calculation algorithm in C++ then create a bridge between React Native and Android/iOS where I can run the code on a thread beside the UI thread then return the value to the JavaScript part of the app.
    • Using C++ in heavy calculations should give you a boost in performance and will help you keep your algorithm in one place (For easier maintenance and debugging).
    • You can also write the algorithm twice using Java/Kotlin for Android and Objective-C for iOS, This method is useful to avoid any C++ code plications but again you're writing the same code twice in different languages (So you'll face other plications).
    • Check out this article to learn more about Native Modules/Bridges.
    • Also check out this article to get information about C++ for Android.
  • Another way to solve this problem is to move the algorithm to a centralized server where you calculate the values and store them on the server then retrieve them using some kind of web API.
  • Now if you want (for some reason) to keep your algorithm in JavaScript, You'll have to break the calculation process into tiny and lightweight pieces then requestAnimationFrame for every piece, For example, if your algorithm generates a random number then does some calculation on it and repeats this process for 2 million times, You'll need to requestAnimationFrame for every calculation, store the current result somewhere and request another frame for the next calculation.
    • We've to do this because by contract JavaScript has only one thread and all JS code including rending frames on the screen happens on this thread so we break our code into small pieces to allow for new frames to be rendered in between.
    • Check out this article to learn more about dividing workloads and animation frames.

Good Luck

本文标签: javascriptHow to implement code with long execution time in React NativeStack Overflow