简体   繁体   中英

Avoiding callback hell in Realm.open for nodejs/react-native

Look at this example from Realm's getting started . It suffers from clalback hell and it gets only worse if you need to do more complicated writes.

Realm.open({schema: [CarSchema, PersonSchema]})
  .then(realm => {
    // Create Realm objects and write to local storage
    realm.write(() => {
      const myCar = realm.create('Car', {
        make: 'Honda',
        model: 'Civic',
        miles: 1000,
      });
      myCar.miles += 20; // Update a property value
    });

    // Query Realm for all cars with a high mileage
    const cars = realm.objects('Car').filtered('miles > 1000');

    // Will return a Results object with our 1 car
    cars.length // => 1

    // Add another car
    realm.write(() => {
      const myCar = realm.create('Car', {
        make: 'Ford',
        model: 'Focus',
        miles: 2000,
      });
    });

    // Query results are updated in realtime
    cars.length // => 2
  })
  .catch(error => {
    console.log(error);
  });

A good way to avoid abusive usage of callbacks is to have named functions instead of anonymous ones.

Here's what I came with:

     writeMsgs  = () => {
        record = message => {
            id = md5('random thing...')
            doc =  {id             : id                   ,
                    favorite       : message.favorite     ,
                    }
            realm.create(tableName, doc)
        }
        SomethingThatReturnsPromise.then(messages => messages.map(record))
        this.setState( { loading: false, refreshing: false } )
    }
    realmWrite = realm           => realm.write(writeMsgs)
    realmOpen  = ()              => Realm.open(schemas).then(realmWrite)

Then I just need to do realmOpen() for it to trigger realmWrite . The problem is: realm.write takes a callback with no arguments as its argument. BUT inside this callback, the realm object is used. This is only possible if the callback is passed annonymously. If I give it a name, it won't be possible.

I did the following to include realm in the scope:

     writeMsgs  = realm => () => {
        record = message => {
            id = md5('random thing...')
            doc =  {id             : id                   ,
                    favorite       : message.favorite     ,
                    }
            realm.create(tableName, doc)
        }
        SomethingThatReturnsPromise.then(messages => messages.map(record))
        this.setState( { loading: false, refreshing: false } )
    }
    realmWrite = realm           => realm.write(writeMsgs(realm))
    realmOpen  = ()              => Realm.open(schemas).then(realmWrite)

However, Realm complies: cannot modify managed objects oustide of a write transaction

I don't know how the write transaction mechanism works but it looks like it can't be adapted to avoid excessive use of callbacks. For me realm.write(anonymous_function_here_that_actually_writes_things) makes no sense. Why not just real.write(document_to_write) ?

You can wrap realm write write in a promise function, so everything can be chained and linear

const realmWrite(name,obj)=>    
  new Promise((resolve,reject)=>
    realm.write(() => {
      return resolve(realm.create(name,obj))
   })
})


...then(()=>realmWrite('car',{
    make: 'Ford',
    model: 'Focus',
    miles: 2000,
  })) 
.then(car=>{})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM