递归地执行承诺 nodejs [英] execute promises recursively nodejs

查看:73
本文介绍了递归地执行承诺 nodejs的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下函数通过 xmlrpc 在我的服务器上创建新文件夹

var createFolder = function(folder_name) {var defer = Q.defer();client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {如果(错误){if (err.responseString && err.responseString.match('已经存在')) {//使用folder_name+Math.round(Math.random()*100)递归调用相同的函数} 别的 {延迟拒绝(错误);}} 别的 {defer.resolve(folder_name);}});返回 defer.promise;}

函数成功新建文件夹但是,如果文件夹已经存在,我想用新的文件夹名称再次递归地触发这个函数,然后在承诺中返回它,这样无论何时调用这个函数,它都会返回文件夹名称,不管它被执行了多少次

类似的东西

createFolder('directory').then(function(resp){console.log(resp);//可能返回目录 ||目录 1 .... 等});

**编辑**所以我设法通过传递 defer 对象来实现这一点让我知道是否有更优雅的方法来实现这一点

var createFolder = function(folder_name,defer) {推迟=推迟||Q.defer();client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {如果(错误){if (err.responseString && err.responseString.match('已经存在')) {返回 createFolder(folder_name+Math.round(Math.random()*100,defer)} 别的 {延迟拒绝(错误);}} 别的 {defer.resolve(folder_name);}});返回 defer.promise;}

解决方案

这里有一个糟糕简单的方法来解决您的问题:

var createFolder = function(folder_name) {var defer = Q.defer();client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {如果(错误){if (err.responseString && err.responseString.match('已经存在')) {//使用folder_name+Math.round(Math.random()*100)递归调用相同的函数defer.resolve(createFolder(folder_name+Math.round(Math.random()*100)));} 别的 {延迟拒绝(错误);}} 别的 {defer.resolve(folder_name);}});返回 defer.promise;}

但是,defer 被认为是不好的做法. 这是一个 关于承诺的非常好的文章.

你应该喜欢这样的东西:

var createFolder = function(folder_name) {返回 Q.Promise(function(resolve, reject){client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {如果(错误){if (err.responseString && err.responseString.match('已经存在')) {//使用folder_name+Math.round(Math.random()*100)递归调用相同的函数解决(创建文件夹(文件夹名称+Math.round(Math.random()* 100)));} 别的 {拒绝(错误);}} 别的 {解决(文件夹名称);}});});}

正如@Bergi 所指出的,这仍然不正确且难以调试.methodCall 的回调中抛出的任何潜在错误实际上都不会拒绝promise 并且很可能会被吞下(尽管这个回调看起来很少出错,但它可能会演变).请参阅他的回答以获得更好的方法.

另外,请参阅此处的官方 Q 文档.>

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;
}

解决方案

Here is a bad simple way of solving your problem:

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;
}

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

You should favor 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);
        }
      });
  });
}

EDIT: as noted by @Bergi, this is still not right and hard to debug. Any potential errors thrown from the callback of methodCall won't actually reject the promise and will most likely be swallowed (even though this callback seems very little error-prone, it might evolve). Please refer to his answer for a better way of doing this.

Also, see the official Q doc here.

这篇关于递归地执行承诺 nodejs的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆