递归javascript函数返回乱序?

时间:2018-03-16 21:32:39

标签: javascript node.js recursion github-api

所以我有以下代码尝试以递归方式查找Github存储库中的文件。

文件夹结构如下所示

  

主:

     

master:gpapi /

     

master:Documentation /

     

主:文档/ AUTH /

     

master:Documentation / download /

     

主:文档/搜索/

我希望输出看起来像这样:

  

(主人:电话) - > master:Documentation /是一棵树!

     

(主人:文件/电话) - > master:Documentation / auth /是一棵树!

     

(master:Documentation / auth / call) - > master:Documentation / auth / contents

     

(主人:文件/电话) - > master:文档/下载/是一棵树!

     

(主人:文件/下载/电话) - > master:文档/下载/内容

     

(主人:文件/电话) - > master:Documentation / search /是一棵树!

     

(主人:文件/搜索/电话) - > master:文档/搜索/内容

     

(主人:文件/电话) - > master:文档/内容

     

(主人:电话) - > master:gpapi /是一棵树!

     

(master:gpapi / call) - > master:gpapi / contents

     

(主人:电话) - > master:内容

相反,输出看起来像这样:

  

(主人:电话) - > master:Documentation /是一棵树!

     

(主人:电话) - > master:gpapi /是一棵树!

     

(主人:电话) - > master:内容

     

(主人:文件/电话) - > master:Documentation / auth /是一棵树!

     

(主人:文件/电话) - > master:文档/下载/是一棵树!

     

(主人:文件/电话) - > master:Documentation / search /是一棵树!

     

(主人:文件/电话) - > master:文档/内容

     

(master:gpapi / call) - > master:gpapi / contents

     

(主人:文件/下载/电话) - > master:文档/下载/内容

     

(主人:文件/搜索/电话) - > master:文档/搜索/内容

     

(master:Documentation / auth / call) - > master:Documentation / auth / contents

在最近的调用可以评估文档的子目录/树之前,第一个函数调用如何评估gpapi目录/树?这是我如何进行递归的问题,还是控制台日志记录的工作原理?

这是代码

//Package to connect to GitHub's GraphQL API
var GithubGraphQLApi = require('node-github-graphql') 

//Package to edit SQL db
var sql = require('mysql'); 

//Connect to GitHub API
var github = new GithubGraphQLApi({
  token: process.env.GITHUB_API_TOKEN,
  debug: true
})

//Call the recursive function
populatefiles("googleplay-api", "master:");

//Find all the files in a repo for a given path
function populatefiles(repo_name, path){
    //Query the GitHub API for all files in repo <repo_name>
    //found at <path>
    github.query(`
        {
            viewer {
                repository(name: "` + repo_name +`") {
                    object(expression: "` + path +`") {
                        ... on Tree{
                            entries{
                                name
                                type
                                mode
                            }
                        }
                    }
                }
            }
        }

        `, null, (res, err) => {

        //The array of files returned by Github
        var entries  = res.data.viewer.repository.object.entries

        for (var e in entries){
            var entry = entries[e];

            //If the entry is a directory("tree") 
            if(entry.type === "tree"){

                //update the path and log it
                var newpath = path + entry.name + "/";
                console.log(newpath + " is a tree!");

                //call the function with the new path
                populatefiles(repo_name, newpath);
            }
        }
        //log all entries found at <path>
        console.log(path + " contents");
        //console.log(JSON.stringify(res, null, 2))
    })
}

1 个答案:

答案 0 :(得分:-1)

你正在处理承诺,承诺是异步的。为了让他们同步工作,你必须&#34;链&#34;它们与.then()或类似的东西一起。

我还没有测试过这段代码,但这是一般的想法。您将要分配github.query()的返回值,这将是承诺。然后你可以使用.then()。在for循环中,事情变得有趣。

我在这里做的方式(将所有的promises放入一个数组然后调用Promise.all,你无法确定{{1}每次迭代的顺序如果您需要确定订单,那么您也需要将这些订单链接起来。我已在评论中插入了示例代码。(请参阅for行)。

pr2

*编辑:我忘了提到的另一件事:对于承诺,你总是希望在链的末尾至少有一个//Call the recursive function populatefiles("googleplay-api", "master:") .then(x => console.log('all done')); .catch(e => console.log('error!', e)); //Find all the files in a repo for a given path function populatefiles(repo_name, path) { //Query the GitHub API for all files in repo <repo_name> //found at <path> var pr = github.query(` { viewer { repository(name: "` + repo_name + `") { object(expression: "` + path + `") { ... on Tree{ entries{ name type mode } } } } } } `); pr = pr.then(res => { //The array of files returned by Github var entries = res.data.viewer.repository.object.entries var prarr = []; // var pr2 = Promise.resolve(); // create a resolved promise to start the chain, if you're worried about order of the for loop. for (var e in entries) { var entry = entries[e]; //If the entry is a directory("tree") if (entry.type === "tree") { //update the path and log it var newpath = path + entry.name + "/"; console.log(newpath + " is a tree!"); //call the function with the new path prarr.push(populatefiles(repo_name, newpath)); // pr2 = pr2.then(populatefiles(repo_name, newpath)); // if you're worried about order of the loop } } //log all entries found at <path> console.log(path + " contents"); //console.log(JSON.stringify(res, null, 2)) return Promise.all(prarr); //return pr2; // if you're worried about the order of the loop }); return pr; } ,以防出现错误。如果你没有节点变得非常脾气暴躁,并会给你一个关于未处理的承诺的警告信息。