Replication asynchronously via github API to get files

I use the github API to go through the repo and get a list of all the files in it. This structure is called a "tree." A tree is basically a subdirectory. Therefore, if I want to see the contents of a tree, I need to make a GET request to the identifier of this tree. The response will be an array of objects representing the elements in this tree. But some of these elements will also be trees, so I will have to make another request for this tree. A repo might look like this:

|src
    app.jsx
    container.jsx
    |client
        index.html
readme.md

This structure will be represented by the following objects

[
    { name:'src', type:'tree', id:43433432 },
    { name:'readme.md', type:'md', id:45489898 }
]
//a GET req to the id of the first object would return the following array:
[
    { name:'app.jsx', type:'file', id:57473738 },
    { name:'contain.jsx', type:'file', id:748433454 },
    { name:'client', type:'tree', id:87654433 }
]
//a GET req to the id of the third object would return the following  array:
[
    { name:'index.html', type:'file', id:44444422 }
]

I need to write a function that will return an array of names of all files. This is rather complicated as I try to combine asynchronous calls with recursion. This is my attempt:

function treeRecurse(tree) {
  let promArr = [];  

  function helper(tree) {    
    tree.forEach(file => {      

      let prom = new Promise((resolve, reject) => {
        if (file.type == `tree`) {
          let uri = treeTrunk + file.sha + `?access_token=${config.ACCESS_TOKEN}`;          

          request({ uri, method: 'GET' })
            .then(res => {
              let newTree = JSON.parse(res.body).tree;              
              resolve(helper(newTree));              
            });

          } else resolve(promArr.push(file.path));
          promArr.push(prom);
      });
    });
  };
  helper(tree);
  Promise.all(promArr)
    .then(resArr => console.log(`treeRecurse - resArr:`, resArr));
};

, promArr . , , . .

+4
3

1:

let username = 'YOUR_USERNAME';
let reponame = 'YOUR_REPONAME';
let access_token = 'YOUR_ACCESS_TOKEN';

const axios = require('axios');

let tree = [];
let fileNames = [];
function start() {
    axios.get(`https://api.github.com/repos/${username}/${reponame}/git/trees/master?access_token=${access_token}`)
      .then(
        function(res) {
          tree = tree.concat(res.data.tree);
          getFilesNameRecur();
        },
        function(err) {
          console.log(err);
        }
      );
}


function getFilesNameRecur() {
  if (tree.length !== 0) {

    let firstObjectOfTree = tree.pop();
    if (firstObjectOfTree.type === 'tree') {
      axios.get(firstObjectOfTree.url + `?access_token=${access_token}`)
        .then(
          function(response) {
            tree = tree.concat(response.data.tree);
            getFilesNameRecur();
          },
          function(err) {
            console.log(err);
          }
        );
    } else if (firstObjectOfTree.type === 'blob') {
      fileNames.push(firstObjectOfTree.path);
      getFilesNameRecur();
    }
  } else {
    // Finished fetching all file names
    console.log(fileNames);
  }
}

start();

2 ():

async ES2017.

: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

import axios from 'axios';

let username = 'YOUR_USERNAME';
let reponame = 'YOUR_REPONAME';
let access_token = 'YOUR_ACCESS_TOKEN';
let tree = [];
let fileNames = [];
async function start() {
  try {
    let res = await axios.get(`https://api.github.com/repos/${username}/${reponame}/git/trees/master?access_token=${access_token}`);
    tree = tree.concat(res.data.tree);
    while (tree.length !== 0) {
      await getFilesNameRecur();
    }
    console.log(fileNames);
  } catch(e) {
    console.log(e);
  }
}

async function getTreeFromGithub(url) {
  try{
    let response = await axios.get(url + `?access_token=${access_token}`);
    return response.data.tree;
  } catch (e) {
    console.log(e);
    throw e;
  }
}


async function getFilesNameRecur() {
  let firstObjectOfTree = tree.pop();
  if (firstObjectOfTree.type === 'tree') {
    let subTree = await getTreeFromGithub(firstObjectOfTree.url);
    tree = tree.concat(subTree);
  } else if (firstObjectOfTree.type === 'blob') {
    fileNames.push(firstObjectOfTree.path);
  }
}

start();
+2

. , promArr , , , , Promise, Promise.all Promises .

, helper tree arr - arr, Promises. helper(tree, []) - , Promises helper(newTree, updatedArray). , , Promises updatedArray, updatedArray, Promises.

Promise.all(helper(tree, [])).then(...) .

Kinda , - , .

+1

Git.

var gitFake = {0       : [{ name:'src', type:'tree', id:43433432 },
                          { name:'readme.md', type:'md', id:45489898 }
                         ],
               43433432: [ { name:'app.jsx', type:'file', id:57473738 },
                           { name:'contain.jsx', type:'file', id:748433454 },
                           { name:'client', type:'tree', id:87654433 }
                         ],
               87654433: [ { name:'index.html', type:'file', id:44444422 }
                         ],
               getDir  : function(id,cb){ setTimeout(cb, 250, !this[id] && "Error: No such directory..!", this[id])}
              };

getDir, , 250. gitFake.getDir(id,cb), , , - , cb(err,data), . , ;

function promisify(f){
  return data => new Promise((v,x) => f(data, (err,res) => err ? x(err) : v(res)));
}

getAllDirs, ;

function promisify(f){ // utility function to promisify the async functions taking error first callback
  return data => new Promise((v,x) => f(data, (err,res) => err ? x(err) : v(res)));
}

function getAllDirs(root = 0){
  gd(root).then(function(ds){
                  ds.length && (console.log(ds),
                                ds.filter( d => d.type === "tree")
                                  .forEach(d => getAllDirs(d.id)));
                })
          .catch(e => console.log(e));
}

var gitFake = {0       : [{ name:'src', type:'tree', id:43433432 },
                          { name:'readme.md', type:'md', id:45489898 }
                         ],
               43433432: [ { name:'app.jsx', type:'file', id:57473738 },
                           { name:'contain.jsx', type:'file', id:748433454 },
                           { name:'client', type:'tree', id:87654433 }
                         ],
               87654433: [ { name:'index.html', type:'file', id:44444422 }
                         ],
               getDir  : function(id,cb){ setTimeout(cb, 250, !this[id] && "Error: No such directory..!", this[id])}
              },
        gd  = promisify(gitFake.getDir.bind(gitFake));

getAllDirs();
.as-console-wrapper { max-height: 100% !important; top: 0; }
Hide result
+1

Source: https://habr.com/ru/post/1684405/


All Articles