React Native computational heavy task - asynchronous

Very simple and common use case, but I can't find satisfying answer.
I have react native app which needs to store some data locally. I am using redux and redux-observables and Realm as a storage.
What I need is: some action occur, let's say ADD_ITEM. I need to update UI with some payload (standard redux). Then I want to create/transform that payload to another piece of data and save that data into Realm (asynchronously). Whatever I try, it always lags UI (a lot).
I tried to wrap that realm call into promise and use switchMap, but it's still slow.
I haven't took a look at workers yet but they only accept strings, which is let's say much less usable for me.
I can offload completely that computation to native background thread but that will be very uncomfortable and a lot of writing.
Could async await help me? Of redux-saga? I feel like it's the same thing, not real async processing.
Or am I using completely wrong libraries for this?
const insertOrderItem = (action$) =>
action$.ofType(Action.ADD_ORDER_ITEM)
.switchMap(({ payload }) => Rx.Observable.fromPromise(
new Promise((resolve, reject) => {
storage.insert(createObject(payload)
resolve({
type: "OPERATION_ADDED"
})
})
))
In general, storing small piece of data to realm shouldn't be THAT much computational heavy but I feel like it's necessary to do this kind of jobs on background thread.
Am I missing something?
Thanks

I had same problem with my app using React Native + Realm DB. I tried all ways without having to write native code and make the bridge from react-native to native, and finally I found a solution:
https://corbt.com/posts/2015/12/22/breaking-up-heavy-processing-in-react-native.html
Install npm install next-frame --save.
Add next-frame to your code import nextFrame from 'next-frame';
Add this line within a for that took long, or a for which insert in DB await nextFrame();
A complete example would look like this:
import nextFrame from 'next-frame';
let response = await fetch("https://emberall.com/user/1/recordings");
let responseJSON = await response.json();
for (let recording of responseJSON.recordings) {
await nextFrame(); // The javascript will yield here and not resume execution until the next frame.
mergeRecordingToLocalDatabase(recording);
}
Basically what this does is that in every iteration or db-insert it waits for JS to render and process next UI frame, so your app will not get stuck or freeze.
P.D.: I know months have passed since question but I think a lot o people could benefit from this.

It's laggy because JS run in one thread. So if you wrap your code in Promise, it's still in one thread.
I think best solution for your is transfer data over React Native bridge to native and do this transform in native code. For guide how to communicate with native code look here

I'm not familiar with Realm, but I can't seem to find the storage.insert API you're using. I only see realm.write() transactions. I was trying to see if they had a truly non-blocking, asynchronous API but it appears Realm does not offer one for their JavaScript bindings.
They do appear to offer non-blocking APIs in their Java bindings with executeTransactionAsync() but that is not likely an option for you.
Seems like your options would be: do it in native on another thread, or some how reduce the write overhead (smaller object, write at a time where it's not noticeable, etc)

Related

What is the best practice for server-side code in Meteor?

I'm new to the world of coding and Web dev and for my first real project, I've started building a quiz web app using Meteor.
Long story short, the app basically displays a random question to the user, then takes in their answer and gets feedback (it's a bit more complicated than that, but for the purposes of this question, that's the main functionality).
I've managed to get it working, but pretty much everything (apart from account creation and that kind of stuff) is done on the client-side (such as getting the random qn) - which I'd imagine is not very secure..
I'd like to move most of the calculations and operations on the server, but I don't want to publish any of the Questions collection to the client, since that means the client can essentially change it and/or view the correct answer.
So, my question is, would it be considered 'bad practice' if I don't publish anything to the client (except their user document) and basically do everything through Meteor methods (called on the client, and executed server-side)?
I've already tried implementing it and so far everything's working fine, but was just wondering whether it's good practice. Would it hurt performance in any way?
I've searched online for a while, but couldn't really find a definitive answer, hence my post here... TIA
The below example pulled right from the documentation showing how to omit fields.
// Server: Publish the `Rooms` collection, minus secret info...
Meteor.publish('rooms', function () {
return Rooms.find({}, {
fields: { secretInfo: 0 }
});
});

Firestore Document get request promise doesn't resolve. How do I solve this problem?

Summary
I am using react-native-firebase in my project, and I am running pure react-native (No Expo). However, on putting a get request to any document on Firestore never gives a response. That is, in a try-catch block, neither does it resolve, nor does it get rejected, it keeps on going forever and ever.
(And yeah, I know about promises and I am using await/async so its not about waiting for the promise to complete, in fact, the main thing is that promises are not getting resolved/rejected)
The main issue is that this problem comes randomly, its not like it fails every time, it does it randomly. On close observation, I also observed that this happens mostly when I am constantly doing get requests, for example, I have a query which checks for the latest version in a document, now whenever I reload the app, this get query is made, and on 2-3 frequent reloads, this query never resolves.
I can do all other Firebase stuffs, like checking authentication, setting documents data, deleting, modifying editing etc. But this doesn't work out
A Bit of Background Story
This is my first project in react-native and react-native-firebase. In the past, I have been working on Ionic, and native Android (Java). I never faced this issue there. I have been searching on the internet a lot, and a few solutions that I got were mainly for the Firebase Web SDK, and not for react-native-firebase.
I found one solution, about resetting user from the Authentication console, but that never worked either. I am putting forward the link which I found (for reference, as my problem is quite similar to this, and mainly differs in the fact that I use react-native-firebase, and not the Firebase Web SDK).
https://github.com/firebase/firebase-js-sdk/issues/533
Code Samples
Get Queries (Few Code Samples which I am using)
let updateData = await firebase.firestore().doc('Updates And Errors/Updates').get();
var expensesDoc = await firebase.firestore().doc(`NewExpenses/${dateToday}`).get()
Expected Output
All Get queries should function at all times.
Actual Output
Get Queries only work when they are not called frequently. (I know its quite weird)
Have you tried using regular promise (then/catch) syntax? I have personally noticed some promise inconsistencies while using the react-native-firebase library with redux-saga's call as well (it simply didn't work, just like you mentioned). To solve my issue, I simply wrapped all the requests in functions that return a new, actual promise, which somehow worked. Still a mystery why though.
Example:
function get (query) {
return new Promise((resolve, reject) => {
query.get()
.then(data => resolve(data))
.catch(err => reject(err))
})
}
// Later use:
await get(firebase.firestore().doc('yourDoc'))
If you ever find a proper solution, please let me know, as this code obviously smells.

With React / Redux, is there any reason not to program the store globally?

I love Redux, but to use it, I have LOTS of additional code scattered all over my application: connect, mapDispatchToProps, mapStateToProps etc etc
It appears to me however that I should be able to both dispatch to the store and get any value from the store via a global window level reference to the store object. If I did this, it would cut alot of code out of my application.
So the question is, what is wrong with this approach? Why NOT do all my Redux disptach and state access via window.store?
I wrote a long Reddit comment a while back about why you should use the React-Redux library instead of writing store code by hand.
Quoting the main part of that answer:
First, while you can manually write the code to subscribe to the Redux store in your React components, there's absolutely no reason to write that code yourself. The wrapper components generated by React-Redux's connect function already have that store subscription logic taken care of for you.
Second, connect does a lot of work to ensure that your actual components only re-render when they actually need to. That includes lots of memoization work, and comparisons against the props from the parent component and the values returned by your mapStateToProps function for that component. By not using connect, you're giving up all those performance improvements, and your components will be unnecessarily re-rendering all the time.
Third, by only connecting your top-level component, you are also causing the rest of your app to re-render unnecessarily. The best performance pattern is to connect lots of components in your app, with each connected component only extracting the pieces of data it actually needs via mapStateToProps. That way, if any other data changes, that component won't re-render.
Fourth, you're manually importing the store into your components, and directly coupling them together, thus making it harder to test the components. I personally try to keep my components "unaware" of Redux. They never reference props.dispatch, but rather call pre-bound action creators like this.props.someFunction(). The component doesn't "know" that it's a Redux action creator - that function could be a callback from a parent component, a bound-up Redux action creator, or a mock function in a test, thus making the component more reusable and testable.
And finally, the vast majority of apps built using React and Redux use the React-Redux library. It's the official way to bind the two together, and doing anything else will just confuse other developers looking at your project.
Also, per the Redux FAQ entry on importing the store directly:
While you can reference your store instance by importing it directly, this is not a recommended pattern in Redux. If you create a store instance and export it from a module, it will become a singleton. This means it will be harder to isolate a Redux app as a component of a larger app, if this is ever necessary, or to enable server rendering, because on the server you want to create separate store instances for every request.
Summarizing all that:
Better performance
Lower coupling via dependency injection of the store
Better testability
Better architecture
I'd also suggest you read through my two-part post The Tao of Redux, Part 1 - Implementation and Intent, and The Tao of Redux, Part 2 - Practice and Philosophy. These two posts discuss the history and intent behind Redux's design, how it's meant to be used, why common usage patterns exist, and other ways that people may use Redux.

Streaming an http response within a composed action in Play! Framework 2.1

I'm creating an authentication action that wraps other actions, using the Play Zentasks sample app as a template. One of the things that this needs to be able to do, is hit a webservice in certain circumstances, in order to retrieve a user's details. I want to do this in a non-blocking fashion, but I don't want to have to pass a future back to the action that I'm wrapping.
The only way that I can think of doing this is by using Enumerator.fromStream() with an InputStream pulled from a URL object. I'm guessing this isn't the best way though, since it seems like a duplication of efforts (considering the ws object). The async ws api (and underlying asynchttpclient) returns a Future for everything however. I don't suppose anyone has tackled this issue before and could point me in another direction? Is there something that I'm missing? Also, would using a Enumerator.fromStream() as I've suggested definitely not block?
Thanks in advance,
Suche
You can use the async WS api. When it returns a future, you can call map on that, and pass the value to the action you're wrapping. Now you have a future containing the result of your wrapped action. Turn that into an AsyncResult or just wrap the whole thing in an Async{} block and it should work.

Is there an ObserveOnDispatcher for Windows Store Apps?

I'm using reactive extensions (well, trying, learning) in a windows store app. I have a series of async operations that will eventually navigate to an authorization web page for RTM. Given the reading I've done, I would expect to write something like the following:
var result = rtm
.GetFrob()
.Select(s => rtm.GetAuthenticationUrl(s))
.ObserveOnDispatcher()
.Do(uri => AuthWebView.Navigate(new Uri(uri)))
.First();
However, I can't seem to find a method ObserveOnDispatcher, and further there is no Scheduler.Dispatcher property either, leading me to think on a Windows Store application there is something deeper gong on with the main UI thread and how you reference it.
GetFrob, btw, creates an IObservable sequence using Observable.FromAsync (if that helps with this).
BTW, if I remove that line, I fail in the call to the Navigate as posting it from the wrong thread. So, what is the proper thing to do here to make sure I'm back on the correct thread?
BTW, Excuse the ".Do" operation here, I know it isn't "nice", however, I'm still experimenting in throw-away code.
Many thanks in advance!
Argh. Apparently I just am not good enough at search. :(
Turns out that adding the nuget package Rx-Xaml includes the proper assemblies for the scheduler, etc. Details can be found on the main Rx blog. Of course, my app is back to hanging now, but that may be due to something else dumb on my part.

Resources