ahhmarr ahhmarr - 6 months ago 10
Node.js Question

execute promises recursively nodejs

the following function creates new folder on my server via xmlrpc

var createFolder = function(folder_name) {
var defer = Q.defer();
client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {
if (err) {
if (err.responseString && err.responseString.match('already exist')) {
//call the same function recursively with folder_name+Math.round(Math.random()*100)
} else {
defer.reject(err);
}
} else {
defer.resolve(folder_name);
}
});
return defer.promise;
}


The functions creates a new folder successfully
However, if folder already exists i want to fire this function again recursively with new folder name and then return it in promise so that whenever this function is called it'll return the folder name doesn't matter how many times it was executed

something like

createFolder('directory').then(function(resp){
console.log(resp);// may return directory || directory1 .... etc
});


**EDIT **
so i manged to achieve this by passing the defer object
let me know if there are more elegant ways of achieving this

var createFolder = function(folder_name,defer) {
defer =defer || Q.defer();
client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {
if (err) {
if (err.responseString && err.responseString.match('already exist')) {
return createFolder(folder_name+Math.round(Math.random()*100,defer)
} else {
defer.reject(err);
}
} else {
defer.resolve(folder_name);
}
});
return defer.promise;
}

Answer
var createFolder = function(folder_name) {
  var defer = Q.defer();
  client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {
    if (err) {
      if (err.responseString && err.responseString.match('already exist')) {
        //call the same function recursively with folder_name+Math.round(Math.random()*100)
        defer.resolve(createFolder(folder_name+Math.round(Math.random()*100)));
      } else {
        defer.reject(err);
      }
    } else {
      defer.resolve(folder_name);
    }
  });
  return defer.promise;
}

Should do the trick here.

However, defer is considered bad practice. Here is a very nice article about promises.

If you use Q, you should favour something like:

var createFolder = function(folder_name) {
  return Q.Promise(function(resolve, reject){
     client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {
        if (err) {
          if (err.responseString && err.responseString.match('already exist')) {
            //call the same function recursively with folder_name+Math.round(Math.random()*100)
            resolve(createFolder(folder_name+Math.round(Math.random()*100)));
          } else {
            reject(err);
          }
        } else {
          resolve(folder_name);
        }
      });
  });
}

See the official Q doc here.