递归地执行承诺 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.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屋!