Javascript 如何递归调用异步函数?

Javascript 如何递归调用异步函数?,javascript,node.js,asynchronous,recursion,Javascript,Node.js,Asynchronous,Recursion,我定义了这个函数: // 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: 't

我定义了这个函数:

// 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文档(SalesforceSOAPAPI)要求将检索方法的结果中提供的id传递给检查状态函数

但问题是:

  • 在第一次检查时,如果结果为“完成”,则只需从
    checkRetreInvestatus
    返回回调结果对象(包含结果)

  • 但是如果结果没有完成,我需要再次调用
    checkRetrieveStatus
    。。。从内部
    checkRetrieveStatus

  • 最简单的方法是将原始
    checkRetrieveStatus
    调用中的参数传递到
    checkRetrieveStatus
    的新实例中,但显然不可能知道调用了多少次


  • 听起来我需要一个递归的解决方案?使用while循环会给异步调用带来问题吗?

    最好拆分函数,这样就不必重新输入顶部。类似这样的情况(没有尝试运行此循环,所以只需要了解一下)


    根据您的描述,听起来您只是想调用
    checkRetrieveStatus
    ,直到调用完成,而不是
    retrieve
    checkRetrieveStatus
    。对吗

    如果是这样,那么要做的是将状态签出提取到您自己的函数中,该函数可以递归地调用自身,如下所示:

    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);
    });
    
    如果您担心在重复轮询结果时占用系统资源,可以在检查之间添加延迟:

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

    调用函数并将回调传递给它。调用
    callback
    成功后,在回调内部调用self(下一次迭代)。值得注意的是,递归在理论上是无限的。你可以为递归函数传递一个计数器,但是你不需要知道CAL的数量。我怎么会错过这个?!这太好了,谢谢你的帮助。我从未想过递归调用调用checkRetrieveStatus的函数。
    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);
    });