簡體   English   中英

以遞歸方式執行promises nodejs

[英]execute promises recursively nodejs

以下函數通過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;
}

這些函數成功創建了一個新文件夾但是,如果文件夾已經存在,我想用新的文件夾名稱再次觸發此函數然后在promise中返回它,這樣無論何時調用這個函數它都會返回文件夾名稱並不重要很多次它被執行了

就像是

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

**編輯**所以我通過傳遞延遲對象來實現這一目標讓我知道是否有更優雅的方法來實現這一目標

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

永遠不要在普通(非承諾)回調中做任何邏輯。 在最低級別進行宣傳:

var defer = Q.defer();
client.methodCall('create_folder', [sessionID, folder_name], function(err, resp) {
  if (err) defer.reject(err);
  else defer.resolve(folder_name);
});
return defer.promise;

或者Q.ninvoke更簡單:

return Q.ninvoke(client, 'methodCall', 'create_folder', [sessionID, folder_name]);

現在我們可以開始實現遞歸了。 使用then回調非常簡單,您可以從中回復另一個承諾。 在你的情況下:

function createFolder(folder_name) {
  return Q.ninvoke(client, 'methodCall', 'create_folder', [sessionID, folder_name])
    .catch(function(err) {
      if (err.responseString && err.responseString.match('already exist')) {
        return createFolder(folder_name+Math.floor(Math.random()*100));
      } else {
        throw err;
      }
    });
}

這是解決你的問題的一個的簡單方法:

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

但是, defer被認為是不好的做法。 這是一篇關於承諾非常好的文章

你應該喜歡這樣的東西:

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

編輯:正如@Bergi所指出的那樣,這仍然是不正確且難以調試的。 methodCall的回調中拋出的任何潛在錯誤都不會實際拒絕承諾,並且很可能被吞下(即使這個回調看起來很容易出錯,它可能會發展)。 請參考他的答案以獲得更好的方法。

另外,請參閱此處的官方Q文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM