0

I have two functions.

One queries for project id, project name, and project status and saves them up in an array.This works fine.

function get_All_Projects() {
    var options = {
        method: "get",
        headers: {
            Authorization: "Bearer " + tkft_token
        }
    };
    var url = tkft_url + endpoint + "auth=" + tkft_token + pages;
    var response = UrlFetchApp.fetch(url, options);
    var info = JSON.parse(response);
    var content = info.data;    
    var project_arr = [];
    var identity = {};  
    for (var i = 0; i < content.length; i++) {
        if (content.length > 0) {
            identity.Project_ID = content[i].id;
            identity.Project_Name = content[i].name;
            identity.Project_Start_Date = content[i].starts_at;
            identity.Project_End_Date = content[i].ends_at;
            identity.Project_Status = content[i].project_state; 
            project_arr.push(identity);
        }
    }
    //Logger.log(project_arr);
}

The second function is supposed to use the Id saved up in the project_arr so that I can get all users per project. The challenge is, I am having a hard time including one of the array objects in the URL for this function and also looping through every project id. I keep running into Cannot read property 'length' of undefined error, Is there something I am missing?

function get_By_Users(project_arr) {
    var options = {
        method: 'get',
        headers: {
            Authorization: 'Bearer ' + tkft_token
        }
    };

    for (var i = 0; i<project_arr.length; i++) {  
        var url = tkft_url+ 'projects/'+ project_arr.Project_ID +'/users?auth='+ tkft_token + pages
        var response = UrlFetchApp.fetch(url,options); 
        var info= JSON.parse(response); 
        var content = info.data;
    }

    Logger.log(content);
}
6
  • 1
    How are you calling get_By_Users()? Commented Mar 4, 2020 at 13:25
  • @TheMaster, not sure I understand your question, but to call for all users this is the URL structure /api/v1/projects/<project_id>/users Basically, I should get the project_id from *project_arr in get_All_Projects() function and use it in the URL in the second function Commented Mar 4, 2020 at 13:29
  • 1
    If you're calling get_By_Users() outside of your get_All_Projects() function, project_arr is undefined since it is a local var. Commented Mar 4, 2020 at 13:33
  • 1
    Read this and explain how you are calling this function. Commented Mar 4, 2020 at 13:58
  • 1
    Even though you got a answer, this is basic stuff and it'll do you good if you read and practice basic functions link above. Commented Mar 4, 2020 at 14:11

1 Answer 1

3

I am surprised that this code works with no Promises or async, if it really does a URL fetch. Or is that a mock?

Anyway, rather than a loop and Array.push, you can just use Array.map to do a data transform.

Also, you can use a template string, rather than string concatenation.

function get_All_Projects() {
    const options = {
        method: "get",
        headers: {
            Authorization: "Bearer " + tkft_token
        }
    };
    const url = `${tkft_url}${endpoint}auth=${tkft_token}${pages}`
    const response = UrlFetchApp.fetch(url, options);
    const info = JSON.parse(response);
    const content = info.data;    
    const project_arr = content.map(item => ({
        Project_ID: item.id;
        Project_Name: item.name;
        Project_Start_Date: item.starts_at;
        Project_End_Date: item.ends_at;
        Project_Status: item.project_state; 
    }))
    return project_arr
}

Then you need to call get_By_Users with the project_arr:

const allProjects = get_All_Projects()
get_By_Users(allProjects)

This one flattens down even more with Array.map.

async function get_By_Users(project_arr) {
    var options = {
        method: 'get',
        headers: {
            Authorization: 'Bearer ' + tkft_token
        }
    };

   const makeUrl = p => `${tkft_url}projects/${p.Project_ID}/users?auth=${tkft_token}${pages}`

  const safeJSONparse = item => {
    try {
      return JSON.parse(item)
    } catch (e) {
      return {data: undefined}
    }
  }

  const data = project_arr.map(p =>
     safeJSONparse(UrlFetchApp.fetch(makeUrl(p), options)).data))

    Logger.log(data);
}

You always need to try / catch with JSON.parse, because it throws if it can't parse the input. You then need to decide how your application will behave when this happens. 20% of coding is getting it to work. The other 80% is coding for what happens when it doesn't work.

See this article for why to use Array.map, and this one for why to use const.

Sign up to request clarification or add additional context in comments.

2 Comments

I am surprised that this code works with no Promises or async, if it really does a URL fetch. See tag urlfetch info page
Interesting - I'd never seen that before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.