I amtrying to call Google Tasks API for a app I'm building.When I make the call using Google's client libraries, it succeeds and return what is expected.
function getAllTasks() {
gapi.client.tasks.tasks.list({
tasklist: 'MDIxODc1MzEwNzc4MzMxNDU2MTU6MDow'
}).then(function (response) {
console.log(response);
var arr = response.result.items;
console.log(arr);
for(var j=0;j<arr.length;j++){
console.log(arr[j].title);
}
})
}
But when I do the same using jQuery, I get 404 with the text "Login Requied" in the response body.
function getAllTasksJquery() {
$.get("https://content.googleapis.com/tasks/v1/lists/MDIxODc1MzEwNzc4MzMxNDU2MTU6MDow/tasks",function (data,status) {
console.log(data,status);
var arr = data.result.items;
console.log(arr);
for(var j=0;j<arr.length;j++) {
console.log(arr[j].title);
}
});
}
Can someone tell me what am I doing wrong ?
So after hours of search, I finally figured this out. Since I was using the Google's JS Client libraries, I almost ignored the fact that I have to pass my oauth2 access_token with each API call. Only then will the API know the account to access.
More specifically, pass the access_token in the header while making API requests. Here is a jQuery snippet for the same :
$.get(`https://www.googleapis.com/tasks/v1/users/#me/lists`,{access_token: AccessToken}, function (data,status) {
console.log(status,data);
});
Hope it helps the others...
Related
I'm trying to send a "large" table in OfficeJS:
functionfile.html loaded from manifest route
<script>
(function (){
"use strict";
Office.initialize = function (reason) {
$(document).ready(function() {
$("#send-data-button").click(send_data);
});
};
function send_data() {
return Excel.run( function(context) {
var data = context.workbook.worksheets.getItem("SheetName")
.getRange("A1:K3673").load("values");
return context.sync().then( function() {
// 2d table is correctly seen
// $("body").append(data.values);
// Just gets lost in ajax call
$.ajax({
type: "GET",
url: mysite,
data: {"accessData": data.values},
}).done( function(success) {
$("body").append("All Done");
}).fail( function(error) {
$("body").append("Error == " + JSON.stringify(error));
});
return context.sync();
});
});
}
})();
</script>
<div> <button id="send-data-button"> Send </button></div>
However i'm not sure how to send this, on the backside I have a flask server catching the request and was hoping I could just use pandas.read_json but no matter how I try to send this i'm getting different errors. Here's the printout of flask.request when data.values[0][0]:
CombinedMultiDict([ImmutableMultiDict([('update_date', '43191'), ('accessData', 'Channel')]), ImmutableMultiDict([])])
And when I try data.values[0] I get a list of values, which is what i'd expect
CombinedMultiDict([ImmutableMultiDict([('update_date', '43191'), ('accessData[]', 'Channel'), ... <All my column headers>, ImmutableMultiDict([])])
But when I try to send the 2D array with just data.values I get an error message in ajax.fail:
Error == {"readyState":0,"status":0,"statusText":"error"}
I also tried JSON.stringify(data.values) and got the same error message:
Error == {"readyState":0,"status":0,"statusText":"error"}
I even tried to take each column and convert them to some kind of list as nested keys inside accessData but I was getting the same error message. Any help would be greatly appreciated.
Ideally, you should isolate the getting-data-from-Excel part from your ajax call part. Right now, the two are intertwined, which makes it both harder to help debug, and just conceptually less clean.
For the Excel part, you should be able to do:
function getExcelData(){
return Excel.run( function(context) {
var data = context.workbook.worksheets.getItem("SheetName")
.getRange("A1:K3673").load("values");
return context.sync()
.then(function() {
return data.values;
});
})
}
This will free you up to then do:
getExcelData().then(function(values) {
$.ajax(...)
});
Note that range.values returns just a regular 2D array, nothing special. So you can try out your ajax call independently of the Excel call (which is yet another reason to separate those out)
how can i handle a jsonp response? i tried to search but i cant solve it. the screen shot below shows a jsonp result.1
i get that jsonp response using this code, services.js
var app=angular.module('F1FeederApp.services', []);
app.config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'http://ergast.com/**'
]);
});
app.factory('ergastAPIservice', function($http) {
var ergastAPI = {};
var urlFiltered = 'http://ergast.com/api/f1/current/driverStandings.json';
ergastAPI.getDrivers = function() {
return $http({
method: 'JSONP',
url: urlFiltered
});
}
return ergastAPI;
});
now, i access it using the code below and gives me result on the 1st picture.
angular.module('F1FeederApp.controllers', []).
controller('driversController', function($scope, ergastAPIservice) {
$scope.nameFilter = null;
$scope.driversList = [];
// //ergastAPIservice.getDrivers() ->> when i try this i get error this is not a function.
//ergastAPIservice.getDrivers().success(function (response) {
//Dig into the responde to get the relevant data
// $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings;
//});
//code above doesnt work so i tried to access it or atleast show a value like
// the code below
console.log(ergastAPIservice.getDrivers());
console.log(ergastAPIservice.getDrivers().MRData.StandingsTable.StandingsLists[0].DriverStandings);
});
now i get the 1st picture using console.log(jsonp response).
how can i get the list of drivers in that response?,
like: collectionVar = response.getDrivers();.
any link or same problem links would help thanks!
Do something like this. This should work . You are getting a promise . Promises are handled like below. Learn more about promise
app.controller("testController", function($scope,testService){
testService.getDrivers ()
.then(function (response) {
$scope.standingTable = response.data.MRData.StandingsTable.StandingsLists[0].DriverStandings;
// handle valid reponse
},
function(error) {
//handel error
});
}
Big thanks for Noman! i didnt know that i was getting a angular promise response at first. though i want to get the driver standing list. so i use this code.
$scope.driversList = response.data.MRData.StandingsTable.StandingsLists[0].DriverStandings;
I am kind of stuck on how to handle this solution. The frameworks I'm currently working with is node.js and express.js with pug for views/rendering html. What I am trying to do is render to a single page and use values from separate http get requests from different sites. I want express/node to query the external api's and render a view that I will retrieve via ajax call from the client side javascript. The ajax call using jquery from the client side I have figured out. My issue is how to handle multiple external API calls and place the results into an object to render in my pug view. I'm not sure what the best practice would be to execute this properly. Do I create a model? Also, how do I handle the asynchronous http gets? Use promises? I'm kind of new to node and javascript so I'm trying to see what the best conventions to use.
I hope this makes sense.
Thanks!!!!
apiInfoModel.js
var apiCallInfo = {
apiInfo1: APIDATA
apiInfo2: APIDATA2
apiInfo3: APIDATA3
}
Should I have a function that I call that would return the APIDATA?
apiCalls.js
function getApiInfo1() {
return http.get
}
function getApiInfo2() {
return http.get
}
function getApiInfo3() {
return http.get
}
apiInfoController.js
var apiInfo = require('./apiInfoModel')
var apiCalls = require('./apiCalls')
exports.apiInfo = function(req,res,next){
apiInfo.apiInfo1 = apiCalls.getApiInfo1
apiInfo.apiInfo2 = apiCalls.getApiInfo2
apiInfo.apiInfo3 = apiCalls.getApiInfo3
res.render('apiInfo',{apiInfo: apiInfo})
}
To expand on the comment by #Mauricio Noris Freire
apiCalls.js - Add callback parameters
function getApiInfo1(cb) {
return cb(http.get)
}
function getApiInfo2(cb) {
return cb(http.get)
}
function getApiInfo3(cb) {
return cb(http.get)
}
apiInfoController.js - nest the callbacks to have access to all the results
var apiInfo = require('./apiInfoModel')
var apiCalls = require('./apiCalls')
exports.apiInfo = function(req,res,next){
apiCalls.getApiInfo1(function(info1Result) {
apiCalls.getApiInfo2(function(info2Result) {
apiCalls.getApiInfo3(function(info3Result) {
// now you have all 3 results
apiInfoResult = {
apiInfo1: info1Result,
apiInfo2: info2Result,
apiInfo3: info3Result
}
res.render('apiInfo', { apiInfo: apiInfoResult })
});
});
});
}
This nested structure is referred to as the pyramid of doom because it keeps growing with every asynchronous action you need to do. It can be improved by using a utility library like async https://www.npmjs.com/package/async:
async.parallel( [
apiCalls.getApiInfo1,
apiCalls.getApiInfo2,
apiCalls.getApiInfo3
], function(error, apiInfoResult) {
apiInfoResult = {
apiInfo1: info1Result,
apiInfo2: info2Result,
apiInfo3: info3Result
}
res.render('apiInfo', { apiInfo: apiInfoResult })
});
But the currently recommended way is to use Promises. This is a new API introduced in JavaScript to handle this kind of situations. It's available in recent NodeJS versions. It removes the need for callbacks:
apiCalls.js - Return promises instead of using callbacks (the fetch library does this)
require('whatwg-fetch')
function getApiInfo1() {
return fetch()
}
function getApiInfo2() {
return fetch()
}
function getApiInfo3() {
return fetch()
}
apiInfoController.js - Use Promise.all.
const [
apiInfo1,
apiInfo2,
apiInfo3
] = Promise.all([apiCalls.getApiInfo1, apiCalls.getApiInfo2, apiCalls.getApiInfo3]);
apiInfoResult = { apiInfo1, apiInfo2, apiInfo3 }
res.render('apiInfo', { apiInfo: apiInfoResult })
I need to send multiple get requests(required) one by one. When the count is 2-3, it works fine, but with almost 6 HTTP Get requests, sometimes some of them fails and give Internal Sever Error(500). Opening the error link in new tab gives required results.
So there is nothing wrong from server side.
I'm facing this problem both in : localhost and production.
How to deal with this situation from client side?
I've tried:
NodeJS + SocketIO to send data from server without asking. [with so much data if socket keeps writing till 60 sec. socket re-registers & restarts from beginning.]
Angular + NGResource. [internally uses http get. issue persists.]
Angular + Restangular Lib. [internally uses http get. issue persists.]
Please suggest how do I know what the problem is. Then only I can think of a solution.
Thnx!!
Here's a function in which you can wrap your HTTP calls. It will repeat the call until it passes. Beware! If the HTTP call fails 100% of the time (for example, malformed URL), then the function will not stop (In testing, the function was called >70,000 times. Apparently there is no recursion limit with promises). For that case, I've included a limited version of the function that stops after n attempts.
var persistentRequest = function(requestFn) {
var deferred = $q.defer();
requestFn().then(function() {
deferred.resolve();
}, function() {
persistentRequest(requestFn).then(
function() {
deferred.resolve();
}
);
});
return deferred.promise;
}
var persistentRequestLimited = function(requestFn, n) {
var deferred = $q.defer();
if (n <= 0) {
deferred.reject('Did not complete in given number of tries');
} else {
requestFn().then(function(data) {
deferred.resolve(data);
}, function() {
persistentRequestLimited(requestFn, n-1).then(
function(data) {
deferred.resolve(data);
},
function(rejection) {
deferred.reject(rejection);
}
);
});
}
return deferred.promise;
}
For example, use it like:
persistentRequest(function() {
return $http.get('/myurl');
});
persistentRequestLimited(function() {
return $http.get('/myurl');
}, 10);
Don't forget to inject $q into your controller/service/etc.
I'm new to AngularJS, so please, bear with me. I got the following code:
var testModule = angular.module("testModule", ['ngResource']);
testModule.config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'https://api.twitter.com/**']);
});
testModule.controller("SecondController",
function SecondController($scope, $resource){
$scope.secondField = "Hello World";
try{
var restClient =
//$resource("https://api.github.com/repos/angular/angular.js/issues", [],
$resource("https://api.twitter.com/1.1/search/tweets.json", [],
{
"get":{method:"GET", headers:{"Accept":"application/json"},
interceptor: {
"response":function(data){
alert("Response: " + data);
},
"responseError":function(data){
alert("Error: " + data);
}
}
}
});
$scope.about = restClient.get();
} catch(err) {
$scope.error = err.message;
}
$scope.done = true;
}
);
It's supposed to execute the responseError function and data.status should be equal to 215 (the request requires authentication to pass successfully). Instead, the response code is 0.
I'm actually trying to reach a different API (that does not require authentication), but the status code is also 0 and I don't really have any idea what the issue might be. The only successful request I could execute till now is:
GET https://api.github.com/repos/angular/angular.js/issues
Executed by $resource.query(). But nor twitter, nor the target API can be reached. I hope providing me a solution for the twitter example can help me solve my issue.
Thanks.
Edit: Using AngularJS 1.2.0 rc2
This may be because of cross domain request. Status code 0 will come when you try to access web service of different domain. In this case you need to use JSONP as method in ngResource.
http://docs.angularjs.org/api/ngResource.$resource