递归执行承诺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;
}
函数创建新文件夹成功
但是,如果文件夹已经存在,我想用新的文件夹名称递归地再次触发这个函数,然后 return 它承诺,这样无论何时调用这个函数,它都会 return 文件夹名称无关紧要执行了多少次
类似
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 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
被认为是不好的做法。这里有一个very nice article about promises。
你应该喜欢这样的东西:
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
的回调抛出的任何潜在错误实际上不会拒绝承诺,很可能会被吞噬(尽管这个回调看起来很少出错,但它可能会演变)。请参考 以获得更好的方法。
另外,参见 the official Q doc here。
切勿在普通(非承诺)回调中执行任何逻辑。在最低级别承诺:
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
回调非常简单,您可以从中 return 另一个承诺。在你的情况下:
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;
}
});
}
以下函数通过 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;
}
函数创建新文件夹成功 但是,如果文件夹已经存在,我想用新的文件夹名称递归地再次触发这个函数,然后 return 它承诺,这样无论何时调用这个函数,它都会 return 文件夹名称无关紧要执行了多少次
类似
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 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
被认为是不好的做法。这里有一个very nice article about promises。
你应该喜欢这样的东西:
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
的回调抛出的任何潜在错误实际上不会拒绝承诺,很可能会被吞噬(尽管这个回调看起来很少出错,但它可能会演变)。请参考
另外,参见 the official Q doc here。
切勿在普通(非承诺)回调中执行任何逻辑。在最低级别承诺:
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
回调非常简单,您可以从中 return 另一个承诺。在你的情况下:
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;
}
});
}