如何recursion调用asynchronous函数?

我定义了这个函数:

// retrieves zip of package manifest supplied var retrieveZip = function(metadataClient, args, callback) { metadataClient.retrieve(args, function(err, result) { metadataClient.checkRetrieveStatus({id: result.result.id, includeZip: 'true'}, function(err, result) { if(result.result.done) { return callback(result); } // else check again!(how??) }); }); } retrieveZip(metadataClient, args, function(result) { console.log(result); }); 

这个想法是,客户端将尝试根据args中提供的元数据检索一个zip文件。 API文档(Salesforce SOAP API)要求将retireve方法的结果中提供的id传递到检查状态函数中。

然而这个问题是这样的:

  1. 在第一次检查,如果结果是“完成”,那么只需从checkRetreiveStatus (包含结果)返回结果对象的callback,
  2. 但如果结果没有完成,我需要再次调用checkRetrieveStatus …从checkRetreiveStatus
  3. 天真的做法是将参数从原始的checkRetreiveStatus调用传递到checkRetreiveStatus的新实例,但显然不可能知道这将被调用多less次。

这听起来像我需要一个recursion的解决scheme呢? 使用while循环会引入asynchronous调用的问题吗?

从你的描述中,这听起来像你只是想调用checkRetrieveStatus直到它完成, 而不是 retrieve checkRetrieveStatus 。 那是对的吗?

如果是这样,要做的事情是提取状态检查到你自己的函数,可以recursion调用自己,就像这样:

 var checkStatus = function(metadataClient, id, callback) { metadataClient.checkRetrieveStatus({ id: id, includeZip: 'true' }, function(err, result) { if (result.result.done) { callback(result); } else { checkStatus(metadataClient, id, callback); } }); }; var retrieveZip = function(metadataClient, args, callback) { metadataClient.retrieve(args, function(err, result) { checkStatus(metadataClient, result.result.id, callback); }); } retrieveZip(metadataClient, args, function(result) { console.log(result); }); 

如果您在重复轮询结果时担心占用系统资源,则可以在检查之间join延迟:

 var checkStatus = function(metadataClient, id, callback) { metadataClient.checkRetrieveStatus({ id: id, includeZip: 'true' }, function(err, result) { if (result.result.done) { callback(result); } else { setTimeout(function () { checkStatus(metadataClient, id, callback); }, 100); } }); }; var retrieveZip = function(metadataClient, args, callback) { metadataClient.retrieve(args, function(err, result) { checkStatus(metadataClient, result.result.id, callback); }); } retrieveZip(metadataClient, args, function(result) { console.log(result); }); 

更好地分裂function,所以你不必重新进入这样的东西(没有试图运行这个,所以只是得到的想法)

 // retrieves zip of package manifest supplied var retrieveZip = function(metadataClient, args, callback) { metadataClient.retrieve(args, function(err, result) { doCheck(result,function(res){ callback(res) }) }); } function doCheck(result,cb){ metadataClient.checkRetrieveStatus({id: result.id, includeZip: 'true'}, function(err, innerResult) { if(result.result.done) { return cb(result); }else{ doCheck( innerResult ,cb) } }); } retrieveZip(metadataClient, args, function(result) { console.log(result); });