CSH
CSH

Reputation: 15

Nested .then()'s Promises

I'm having some difficulty in simplifying the readability of the code I have written, so far I have managed to separate the code into two primary functions, however I'm still suffering with nested .then()'s. I'm not sure if there is any simpler way of writing these two functions. Any advice on structure and pointers in the right direction would be really appreciated.

I should also highlight that the horsePostHandler.init() function is referring to a different module. The function init() shown in this example is part of the racePostHandler.

RacePostHandler.js

function createHorseEntities( raceEntity ) {
    promises = horsePostHandler.init(raceEntity, race.Horse)
    _.each(promises, function( promise ){
        promise.then(function( entity ){
            if ( raceEntity.horses.length === 0 ) {
                controller.update({ "horseUpdate": true, "horseEntity": entity }, raceEntity)
            }
        })
    })
    return raceEntity
}
function init( object ) {
    handler.data = object.data.PARaceCardObject ? object.data.PARaceCardObject : object.data.PABettingObject;
    racePromises = _.map(handler.data.Meeting.Race, function( race ) {
        return Promise.all([ getMeeting(object.promise), controller.find({ x_reference: race.ID }) ])
        .spread(function( meetingEntity, raceEntity ) {
            return doesRaceExist(meetingEntity, raceEntity, race)
        })
        .then(createHorseEntities)
        .catch(errorHandler)
    })
    return racePromises
}

HorsePostHandler.js

The main reason why I separated the RacePostHandler and the HorsePostHandler into individual modules was due to them using different controllers. One interacting with a Race model, the other a Horse model.

function init( raceEntity, horseArray ) {
    promises = _.map(horseArray, function( horse ) {
        return controller.find({name: horse.Name})
        .then(function(horseEntity){
            return doesHorseExist(raceEntity, horseEntity, horse)
        })
    })
    return promises
}

Upvotes: 0

Views: 1220

Answers (2)

Paul Grimshaw
Paul Grimshaw

Reputation: 21044

If you are writing nodejs 7, you can start with --harmony-async-await flag.

This allows the new async / await functionality which is much more readable:

async function run() {
    try {
        let result1 = await myFirstPromise
        let moreResults = await Promise.all([mySecondPromise, myThirdPromise)
        let finalResult = await lastPromise
        finalResult = doSomethingWith(finalResult)
        return finalResult    
   } catch(err) {
        console.warn(err)
   }
}

run()

In your example using latest javascript (ES7 i think) would be:

 async function createHorseEntities( raceEntity ) {
       for (let entity of (await horsePostHandler.init(raceEntity, race.Horse))) {
            if ( raceEntity.horses.length === 0 ) {
                controller.update({ "horseUpdate": true, "horseEntity": entity} , raceEntity)
            }
       }
       return raceEntity;
  }

Upvotes: 2

louisvno
louisvno

Reputation: 689

For me it is a bit strange that the then() is inside the _each. If horsePostHandler.init(raceEntity, race.Horse) returns Promise.all(array of promises) as i understand from your comment, I would rewrite it like this.

    function createHorseEntities( raceEntity ) {
       horsePostHandler.init(raceEntity, race.Horse)
         .then( function(entities) {
           _.each(entities, function( entity ){
                if ( raceEntity.horses.length === 0 ) {
                    controller.update({ "horseUpdate": true, "horseEntity": entity} , raceEntity)
                }
            })
        })
        return raceEntity
    }

Reads more like "first init() then do something with each value".

Upvotes: 0

Related Questions