Reputation: 13
I use fetch to toggl api the code like this.
const getData = (workspaceId, start, end, projectId, page, tmpData) => {
return new Promise((resolve,reject) => {
let result = []
if (tmpData !== null){
result.push(tmpData)
}
fetch('https://toggl.com/reports/api/v2/details?workspace_id='+workspaceId
+'&since='+start+'&until='+end+'&user_agent=api_test&project_ids='+projectId
+'&page='+page, {
method: 'get',
headers: {
'Authorization': 'Basic '+new Buffer(token.api_token+':api_token').toString('base64')
}
}).then(res=>{
return res.json()
}).then(json=>{
if (json.data.length > 0){
result.push(json)
console.log('on page '+page)
getData(workspaceId, start, end, projectId, page+1, result)
} else {
console.log('end on page '+page)
result.push(json)
console.log(result) //this line is log the result successfully
resolve(result) // but this not resolve i don't know why
}
}).catch(err=>{
reject(err)
})
})
}
the toggl api has rate limit to access if you want to get all data you need to increase the parameter (page) to access the next data.
it's not possible to get all data in once request.
Upvotes: 1
Views: 334
Reputation: 62686
Late to the party, glad there's an excepted answer, but I'd fix the OP code by reorganizing a bit. It looks like the fetch() function answers a promise, so there's no need to create a Promise. Next, I'd split the fetching and the recursive call to it into separate methods. First...
// do a fetch, appending to result, answer a promise for the length of data fetched
const fetchAndAppend = (workspaceId, start, end, projectId, page, result) => {
return fetch('https://toggl.com/reports/api/v2/details?workspace_id='+workspaceId
+'&since='+start+'&until='+end+'&user_agent=api_test&project_ids='+projectId
+'&page='+page, {
method: 'get',
headers: {
'Authorization': 'Basic '+new Buffer(token.api_token+':api_token').toString('base64')
}
}).then(res=>{
return res.json() // is this really async? I would have guessed not
}).then(json=>{
result.push(json)
return json.data.length
})
}
That's easy to read: fetch, append to a result, answer the length. Now make a recursive method that calls the fetch...
// keep fetching until no data is returned, answer a promise for the complete data
const getData = (workspaceId, start, end, projectId, page, tmpData, result) => {
result = result || []
return fetchAndAppend(workspaceId, start, end, projectId, page, result)
.then(length => {
return (length)? getData(workspaceId, start, end, projectId, page+1, tmpData, result) : result
})
}
I think this works, and it has the benefit that the next reader can see that it works and can see why it works.
Upvotes: 0
Reputation: 12796
The problem in this case is your getData
to call the second page. In case there would be no data, your resolve would work but now your problem is that you resolve, with nobody listening.
if (json.data.length > 0){
result.push(json)
console.log('on page '+page)
// nobody is listening for the promise to complete
// any resolve called later, will be not handled
getData(workspaceId, start, end, projectId, page+1, result)
}
You could change this in following way, which would then resolve your callback
getData(workspaceId, start, end, projectId, page + 1, result).then(() => resolve(result))
So essentially this is what happens:
With the change on the line as suggested, the flow would be
So you would essentially get 3 resolves
The full code change would then be:
const getData = (workspaceId, start, end, projectId, page, tmpData) => {
return new Promise((resolve,reject) => {
let result = [];
if (tmpData !== null){
result.push(tmpData);
}
fetch('https://toggl.com/reports/api/v2/details?workspace_id=' + workspaceId + '&since='+ start + '&until=' + end + '&user_agent=api_test&project_ids=' + projectId +'&page=' + page, {
method: 'get',
headers: {
'Authorization': 'Basic '+new Buffer(token.api_token+':api_token').toString('base64')
}
}).then(res=>{
return res.json();
}).then(json=>{
if (json.data.length > 0){
result.push(json);
console.log('on page '+page);
getData(workspaceId, start, end, projectId, page+1, result)
.then(() => resolve(result))
.catch(err => reject(err));
} else {
console.log('end on page '+page);
result.push(json);
console.log(result);
resolve(result);
}
}).catch(err=>{
reject(err);
});
});
};
Upvotes: 1