Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promises are not resolved inside change listeners callbacks until tapping the screen #2740

Open
aureliopetrone opened this issue Feb 28, 2020 · 4 comments
Labels

Comments

@aureliopetrone
Copy link

@aureliopetrone aureliopetrone commented Feb 28, 2020

When my app start I show a spinner until the synchronization of my query-synched realm completes.

Goals

When the sync ends the spinner disappears because of the promise resolved.

Expected Results

The promise is resolved and the code go on.

Actual Results

The problem is that since the promises are not resolved until I tap the screen the loading process seems infinite and the spinner doesn't disappear.

Steps to Reproduce

I have this problem since almost 1 year. You can reproduce it by:

  • use create-react-native-app
  • install realm
  • try

Code Sample

        var realm = Database.getRealm()

        var class1 = realm.objects("Class1")
        var class2 = realm.objects("Class2")
        var class3 = realm.objects("Class3")

        await Promise.all(
            [
                Database.susbscribeAndSyncTo(class1),
                Database.susbscribeAndSyncTo(class2),
                Database.susbscribeAndSyncTo(class3),
            ]
        )

        // This console.log is not executed until I don't tap on the screen.  
        // More classes I add to this and more times I need to tap the screen
        console.log("Synched")

        return true


static susbscribeAndSyncTo = async (object, object_name) => {
        var subscription = object.subscribe()

        return new Promise((resolve, reject) => {
            subscription.addListener((subscription, state) => {
                if (this.checkSubscriptionState(state, object_name)) {
                    try {
                        subscription.removeAllListeners()
                    } catch (e) {
                        console.log(e.message)
                    }
                    resolve(true);
                }
            })
        });
    }
    static checkSubscriptionState = (state, object_type) => {
        switch (state) {
            case Realm.Sync.SubscriptionState.Creating:
                // The subscription has not yet been written to the Realm
                break;
            case Realm.Sync.SubscriptionState.Pending:
                // The subscription has been written to the Realm and is waiting
                // to be processed by the server
                break;
            case Realm.Sync.SubscriptionState.Complete:
                // The subscription has been processed by the server and all objects
                // matching the query are in the local Realm
                return true

                break;
            case Realm.Sync.SubscriptionState.Invalidated:
                // The subscription has been removed
                break;
            case Realm.Sync.SubscriptionState.Error:
                break;

            default:
                break;
        }

        return false
    }

Version of Realm and Tooling

  • Realm JS SDK Version: Realm JS from 3.4.2
  • Node or React Native: React Native
  • Client OS & Version: Android / iOS
  • Which debugger for React Native: None
@realm-probot realm-probot bot added the O-Community label Feb 28, 2020
@dlombard

This comment has been minimized.

Copy link

@dlombard dlombard commented Mar 4, 2020

Hi @aureliopetrone ,

I did not test your code yet but looking at the code provided, the call to new Promise will not resolve/reject if the if statement is false.

I'm talking about this:
return new Promise((resolve, reject) => { subscription.addListener((subscription, state) => { if (this.checkSubscriptionState(state, object_name)) { try { subscription.removeAllListeners() } catch (e) { console.log(e.message) } resolve(true); } }) });

Try to add a resolve or reject after if (this.checkSubscriptionState(state, object_name)). The promise should complete then

@aureliopetrone

This comment has been minimized.

Copy link
Author

@aureliopetrone aureliopetrone commented Mar 4, 2020

@dlombard but actually there is no error because as I said if I tap everything is ok and the app sync.

@Eyesonly88

This comment has been minimized.

Copy link

@Eyesonly88 Eyesonly88 commented Mar 27, 2020

We have this exact problem too!

@aureliopetrone

This comment has been minimized.

Copy link
Author

@aureliopetrone aureliopetrone commented Mar 31, 2020

Solved like this

static susbscribeAndSyncTo = async (object, object_name) => {
        var subscription = object.subscribe()

        return new Promise((resolve, reject) => {
            subscription.addListener((subscription, state) => {
                if (this.checkSubscriptionState(state, object_name)) {
                    try {
                        subscription.removeAllListeners()
                    } catch (e) {
                        console.log(e.message)
                    }

                    setTimeout(() => null, 30) // Workaround
                    resolve(true);
                    setTimeout(() => null, 30) // Workaround
                }
            })
        });
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.