Deleting rooms using nested promises
If you have the possibility to use it, you could try the async / await pattern. It is however only part of the standard since ecmascript 2017.

The pattern allows you to wait for promise before continuing the execution path. This means you could rewrite your current code in the following syntax



// mock
const User = {
  findOne: async function( param ) {
    return new Promise(resolve =&gt; setTimeout(() =&gt; resolve( param ), 500));
  }
};

const _deleteOneToOneRooms = function(userId, teamMembers) {
  return async function() {
    let user = await User.findOne({ _id: userId });
    for (const member of teamMembers) {
      let foundMember = await User.findOne({ _id: member });
      // do something with that member
    }
  };
};

const removeUser = async function() {
  return _deleteOneToOneRooms( 5, [10, 15, 16] )().then( () =&gt; console.log('done') );
};

// an async function returns a promise in itself, so from outside an async function, you can use the `then` syntax
removeUser().then(() =&gt; console.log('async also done'));
// this will be logged first
console.log('remove user was called, rest is async');




This only gives you an idea from how you could reformat your code using this pattern.

The last piece of code can then also be rewritten like:

const _deleteOneToOneRooms = function(userId, teamMembers) {
  return async function() {
     let deletedUser = await User.findOne({ _id: userId });
     let usersNoCommonTeam = await _getUsersWithNoCommonTeams(deletedUser, teamMembers);
     return await _getOneToOneRooms(userId, usersNoCommonTeam);
  };
};