NodeJS My SQL query with Chain promise

你说的曾经没有我的故事 提交于 2019-12-06 10:33:22

You can resolve a promise using .then and can chain then to resolve multiple promises in a synchronous fashion.

Maybe this will solve your use case.

getCategory()
.then( firstRecords => {

  console.log('firstRecords: ', firstRecords);

  let promises = firstRecords.map( record => getRoom(record) );
  return Promise.all(promises);
})
.then( secondRecords => {

  console.log('secondRecords: ', secondRecords);

  let promises = secondRecords.map( record => getReservationL(record) );
  return Promise.all(promises);
})
.then( thirdRecords => {

  console.log('thirdRecords: ', thirdRecords);
})

Reference: Promise then chaining

The then method returns a Promise which allows for method chaining.

If the function passed as handler to then returns a Promise, an equivalent Promise will be exposed to the subsequent then in the method chain

Refrence: Promise all

The Promise.all() method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects.

Promise.all([ { key: 1 }, Promise.resolve(3), 1, true ])
.then( results => {
    results[0]; // { key: 1 }
    results[1]; // 3
    results[2]; // 1
    results[3]; // true
})

Update #1

Promise.all only accept an array of promise and not object with promises on the key.

# wrong
Promise.all([
    { key: Promise.resolve(1) },
    { key: Promise.resolve(2) },
    { key: Promise.resolve(3) },
])

# right
Promise.all([ 
    Promise.resolve(1), 
    Promise.resolve(2), 
    Promise.resolve(3) 
])

you could do something like this to achieve the what you have mentioned in comments.

getCategory(branch_id)
.then( firstRecords => {

  console.log('firstRecords: ', firstRecords);

  let promises = firstRecords.map( record => {
    return getRoom(branch_id, record.id)
    .then( roomData => Object.assign({}, record, { room : roomData }) )
  });

  return Promise.all(promises)

})

If you want to append the data of the first and second promise, then resolve the promises there only to access the data of both in one place.

Update #2

As you mentioned in comments, this code might help you.

getCategory(branch_id)
.then( categories => {

  let roomPromises = categories.map( category => {
    return getRoom(branch_id, category.id)
    .then( rooms => Object.assign({}, category, { rooms }) )
  });

  return Promise.all(roomPromises)

})
.then( category_rooms => {

  let finalPromise = category_rooms.map( category => {

    let reservationPromises = category.rooms.map( room => {
      return getReservationL(room.id, start_date, end_date)
      .then( reservations => Object.assign({}, room, { reservations }) )
    })

    return Promise.all(reservationPromises)
    .then( room_reservations => {
      return Object.assign({}, category, { rooms: room_reservations })
    });
  })

  return Promise.all(finalPromise)
})
.then( data => console.log(data) )

As your logic contains lot of loop statements for data selection and transformation, you need to refactor it into something like:

getCategory(brandId)
    .then(addRoomData)
    .then(addReservationData)
    .then(handleFinalData)
    .catch(handleError);

For addRoomData and addReservationData functions, you may need to use Promise.all() combined with .forEach().

If you want to write your code in a more readable way, consider using async / await.

I think the more optimize way is to use async.waterfall function of async module. https://caolan.github.io/async

async.waterfall([
function(callback) {
    getSomething(options, function (err, result) {
        if (err) {
            callback(new Error("failed getting something:" + err.message));
            // we should return here
        }
        // since we did not return, this callback still will be called and
        // `processData` will be called twice
        callback(null, result);
    });
},
function(data, callback){
  //do something
}
], function(err,results){
  //get final results
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!