Search code examples
react-nativemobileasync-awaitrealm-js

How to use realm with async fetch request?


I have meet this situation for my requirements:

step 1. save data to local db which in the mobile phone (realm)

step 2. upload the local data to the server, and the server will return the data ids if success step 3. delete the records in local db by the returned ids which get by step2

Realm.open({schema:[MySchame],encryptionKey:getRealmKey()})
        .then(realm =>{
            realm.write(() => {
                // 1. get all step data from db
                let objetcs = realm.objects('MySchema');
                // 2. upload obtained data to server
                if(objetcs.length > 0){
                    let recordArr = [];
                    for (let o of steps){
                        recordArr.push(o.get());
                    }
                   uploadDataToServer(recordArr,(res)=>{
                        //3. filter the uploaded steps and delete them
                        let uploadedSteps = realm.objects('MySchema').filtered('id=$0',res.id);
                        if(uploadedSteps.length > 0){
                            realm.delete(uploadedSteps);
                        }
                    });
                }
            });
            realm.close();
        })
        .catch(error =>{
            console.log(error);
        });

but this is not works as expected, it seems DB is closed too early than networks success callback. Thanks for any ideas.


Solution

  • First create a service like one below

    import repository from "./realmConfig";
    
    let CatalogsService = {
        findAll: function () {
            return repository.objects("CatalogsModel");
        },
    
        save: function (catalogs) {
            repository.write(() => {
                repository.create("CatalogsModel", catalogs);
            });
        },
        delete: function () {
            repository.write(() => {
                let all = repository.objects("CatalogsModel");
                repository.delete(all);
            });
        },
    
        update: function (catalogs, callback) {
            if (!callback) return;
            repository.write(() => {
                callback();
                catalogs.updatedAt = new Date();
            });
        }
    };
    
    module.exports = CatalogsService;
    

    where my realmConfig file is as

    import Realm from "realm";
    
    class CatalogsModel extends Realm.Object { }
    CatalogsModel.schema = {
        name: "CatalogsModel",
        primaryKey: "id",
        properties: {
            id: "string",
            name: "string",
            url: "string",
            status: "int"
        }
    };
    class OffersModel extends Realm.Object { }
    OffersModel.schema = {
        name: "OffersModel",
        primaryKey: "id",
        properties: {
            id: "string",
            name: "string",
            url: "string",
            status: "int",
            machineId: "string",
            machineName: "string"
        }
    };
    
    export default new Realm({
        schema: [CatalogsModel, OffersModel],
        schemaVersion: 1,
        deleteRealmIfMigrationNeeded: true
    
    });
    

    Now import Service.js where you are calling async server call and do your job. For reference see below code

    import CatalogService from './path/to/CatalogService .js'
    
    //get objects
    var catalogs = CatalogsService.findAll();
    
    // fire async function , I prefer axios for network calls
    
    Axios.post("SERVER_URL", {
            data: catalogs
        })
        .then(function (response) {
            if (response.success)
                CatalogsService.delete()
        }
    

    I assume you can easily modify findAll() and delete() method as per your need