Catch Facebook Access token on demand, but how? - javascript

I build a Firefox Extension and i'm using the graph api. At the moment i catch the access token of each user while starting the browser like:
https://stackoverflow.com/questions/10301146/facebook-login-within-a-firefox-add-on
This works fine but kind of stupid, because nobody will use the extension in each firefox session. So what i'm trying to do is, catch the access token or more accurately call the methode Wladimir Palant recommends on demand. My code looks like this, while getAccessToken() is the mentioned method.
onLoad: function (){
var NoteHandler = window.arguments[0];
var sjcl = NoteHandler.sjcl;
NoteHandler.getAccessToken();
decryptionDialog.noteHandler = NoteHandler;
decryptionDialog.sjcl = sjcl;
var currID = decryptionDialog.getID();
if(currID==""){
window.close();
return false;
}else{
http_request = new XMLHttpRequest();
http_request.open('Get', 'https://graph.facebook.com/'+currID+'/notes?access_token='+NoteHandler.token, false);
http_request.overrideMimeType("text/json");
http_request.send(null);
decryptionDialog.value = decryptionDialog.ResponseToArray(http_request.responseText);
....
But the problem is while getAccessToken() is still waiting for the access token, the onLoad()-Method won't wait and goes on. Therefore the NoteHandler.token is null while the request is send. Does anyone have an idea, because i'm relatively new to javascript.

You should rewrite this code to be asynchronous - it shouldn't assume that getAccessToken() will get the result immediately, there should be rather a callback parameter, a function to be called when the operation is done (can be a closure function). Something along these lines:
onLoad: function (){
var NoteHandler = window.arguments[0];
var sjcl = NoteHandler.sjcl;
NoteHandler.getAccessToken(function()
{
decryptionDialog.noteHandler = NoteHandler;
decryptionDialog.sjcl = sjcl;
...
http_request.open('Get', 'https://graph.facebook.com/'+currID+'/notes?access_token='+NoteHandler.token, false);
...
});
}
...
getAccessToken: function(callback) {
...
// All done - call the callback
callback();
}

Related

jQuery.ajax and XMLHttpRequest()?

I am trying to retrieve and execute the script contained in a file "example.js", using an AJAX request.
Let's say the example.js is:
const greetings = {
hello: "Hello",
goodBye: "Good bye"
}
console.log(greetings.hello)
In another file, "get_script.js", I try to execute the code above using AJAX.
The request and execution is working just perfect with jQuery:
$.ajax({
method:"GET",
async: false,
url: "example.js",
success: function (response) {
new Function(response)
}
});
console.log(greetings.goodBye)
//output in the console:
// "hello" - from example.js
// "goodbye" - from get_script.js
while with a new XMLHttpRequest(), it doesn't:
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.status === 200) {
const fn = new Function(xhr.response)
fn();
}
}
xhr.open("GET" , "example.js" , false);
xhr.send();
console.log(greetings.goodBye)
// the file is retrieved without problems.
//output in the console:
// "hello" - still getting the console.log() from example.js!
// So the script is executed, right?
// Uncaught ReferenceError: greetings is not defined
Notes:
in the XMLHttpRequest the function only execute if I store it in a variable and then call it.
I experienced that the async set to false is not the reason of this inequality.
Did I write something wrong in the second code? Can anybody explain the reason of this difference?
Thanks so much in advance!
EDIT 04/08/2022
Looking at the jQuery's functions I found out that their way to automatically execute the retrieved code is to append a script tag with the retrieved code as text and then immediately remove it.
I did that in my code and worked just as $.get():
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.status === 200) {
const script = document.createElement("script")
script.text = xhr.response;
document.head
.appendChild(script)
.parentNode
.removeChild(script);
}
}
xhr.open("GET" , "example.js" , false);
xhr.send();
console.log(greetings.goodBye)
//output in the console:
// "hello" - from example.js
// "goodbye" - from get_script.js
Apparently this is how jQuery does it.
Hope I didn't make any mistakes.
Thanks to user Musa for leading me to the solution!
The $.ajax call executed the script(like if it was in a <script> tag) defining greetings as a global constant and logging the value. The function you created in $.ajax success callback is never executed so is insignificant.
The XHR call does not execute the js, but you do it manually with the fn function.
The problem here is that the constant greetings' scope is limited to the fn function and not global.

Override post requests

I have this code that I put in my console:
XMLHttpRequest.prototype.send = function(body) {
// modifies inputted request
newBody = JSON.parse(body);
newBody.points = 417;
// sends modified request
this.realSend(JSON.stringify(newBody));
}
It is supposed to make the points 417 every time it sends a request, but when I look at the request body, it still says the original amount of points. Any help?
Try to add an alert() or console.log() into your modified XMLHttpRequest.prototype.send to check if it actually works. There is a way to prevent this kind of modifications silently.
As others have noted, the error you are experiencing is hard to diagnose exactly without seeing how you created this.realSend.
However, this code will work:
const send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function (body) {
const newBody = JSON.parse(body);
newBody.points = 417;
send.call(this, JSON.stringify(newBody));
};
Note that instead of storing the original send method on XMLHttpRequest.prototype, I've kept in a separate variable and simply invoked it with the correct this value through send.call(). This seems like a cleaner implementation with less chance for conflicts with other code.
See this codesandbox for a working example.
If your function is not being called, possible fetch is used to make ajax requests.
So you can wrap both functions, like this
const send = XMLHttpRequest.prototype.send;
const _fetch = window.fetch;
XMLHttpRequest.prototype.send = function (body) {
const newBody = JSON.parse(body);
newBody.points = 417;
send.call(this, JSON.stringify(newBody));
};
window.fetch = function(url, options){
let newBody;
if(options.body) {
newBody = JSON.parse(options.body);
newBody.points = 417;
options.body = JSON.stringify(newBody);
}
_fetch.call(this, url, options);
}

How to clean the source code of callback in callback next structure

For example in this case
I would like to call url1, call url2, call url3; , step by step after waiting for previous call back.
For example this is my source code
var pram={};
var url = "http://myapiserver.com/api/test";
var client = Ti.Network.createHTTPClient({
onload : function(e) {
Ti.API.info("first call is success!!");
  var url2 = "http://myapiserver.com/api/test2";
  var client2 = Ti.Network.createHTTPClient({
  onload : function(e) {
   // call URL 3 here!!
   Ti.API.info("second call is success!!");
   },timeout : 3000
  });
client2.open("GET", url);
client2.setRequestHeader('Content-type','charset=utf-8');
client2.send(pram2);
},
timeout : 3000
});
client.open("GET", url);
client.setRequestHeader('Content-type','charset=utf-8');
client.send(pram);
This source code is OK however, if you need more steps, nest structure will be deeper and deeper and difficult to maintenance.
Is there good way to clean this kind of source code??
You should take advantage of CommonJS format to have an http.js file that receives the parameters and callbacks. That should avoid repeating the creation of the HTTPClient object over and over again.
Alloy includes underscore.js out of the box. If you want to run multiple async calls at the same time you can use something like http://underscorejs.org/#after
If you can to do subsequent calls you may want to organice your code in a way that you avoid a callback hell. There is plenty of docs already about different ways to address that. Here is a Sample of an old blog post.
You can try following. It is readable and easy to maintain.
var createClients = function (connections) {
var connection = connections.shift(),
url = connection['url'],
param = connection['param'],
client = Ti.Network.createHTTPClient({
onload: function (e) {
Ti.API.info("Call is success!");
connections[0] && createClients(connections)
},
timeout: 3000
});
client.open("GET", url);
client.setRequestHeader('Content-type','charset=utf-8');
client.send(param);
};
var connections = [
{'url': "http://myapiserver.com/api/test1", 'param': {}},
{'url': "http://myapiserver.com/api/test2", 'param': {}},
{'url': "http://myapiserver.com/api/test3", 'param': {}}
];
createClients(connections);
note that you will end up with empty connections
Also you can use connections to get intance of HTTPClient for each connection or extend (for example) with some specific callbacks for each connection.

writing to a file with php and javascript

So I want to use buttons on my HTML page to call a php program that will write to a text file. What I currently get is a success package from my Ajax function, but the file that it has supposed to have written does not exist.
my HTML
<button type = "button" onclick = "getRequest('changeState.php', changeState('1'), 0)"></button>
my Javascript functions:
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
}
catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) {
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function()
{
if(req.readyState == 4) {
return req.status === 200 ?
success(req.responseText) : error(req.status);
}
}
req.open("GET", url, true);
req.send(null);
return req;
}
function changeState(input)
{
state = input;
document.GetElementById("state_current").innerHTML = state;
}
My PHP file:
<?php
$f = fopen("file.txt");
fwrite($f, "Hello World");
fclose($f);
?>
I'll be honest, I'm very new to php, but my syntax seems fine because I'm not dropping any error messages, and I know that the program runs successfully because I get the success function to run. Have I missed something glaringly obvious?
file.txt should be created, if calling your PHP-script directly. If not probably PHP is not allowed to create it. Unfortunately its not that easy to understand which user is used to run PHP, and this user must have the rights to write to the webroot-folder of the server. As far as I know this depends on how PHP is executed (module vs CGI).
I would give it a try to change the folders access rights to "777" (anyone is allowed to do anything).
The changeState function doesn't get called on success because you are passing the value returned by the changeState function not the function reference, should be:
<button type = "button" onclick = "getRequest('changeState.php', changeState, 0)"></button>
You can also check on the Network Tab on the Developers Tools to see if you actually sent the request to the URL. If you didn't, then there's something wrong with your URL or your server.

ajax success called before request has finished

at my whits end with this...
The problem I have is that around the same time (roughly 60-70 mins through the request) the success function is called for the ajax request, but the tomcat logs prove that the request is still running.
(perspective: the request is supposed to either return an empty string ("") or a html page (of errors) however when the success function is called, it returns a string of length 2 result = " " (2 white space characters)
I cannot get this to reproduce in chrome, only IE (which is a problem as we cater specificity for IE)
At first I though it was a jQuery issue as I have multiple polls running when the request is sent (to update jQuery progress bar info)
However...
When I test this with just one asynchronous ajax request (not jQuery) that calls a Java method that just loops for 3 hours printing out in the log each second, it always calls success around the 3600 second mark (still another 7200 seconds remaining).
Example code:
var http_request = false;
if (window.XMLHttpRequest) {
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/text');
}
}
else if (window.ActiveXObject) {
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!http_request) {
alert('Giving up: Cannot create an XMLHTTP instance');
return false;
}
url += "&random=" + Math.random();
http_request.open('GET', url, true);
http_request.onprogress = function () { };
http_request.ontimeout = function () { };
http_request.onerror = function () { };
http_request.onreadystatechange = function(){
if (http_request.readyState == 4) {
if (http_request.status == 200) {
result = http_request.responseText;
alert("success: ("+result.length+") ["+result+"]");
}
}
};
NOTE: this is not a time-out error (at least not an ajax one) as the ajax time-out options seem to work correctly and return time-out errors accordingly, but as I have said, its not a time-out error...the success function is called too early.
Hope somebody can help :)
Cheers,
Steve.
Update:
I've run the request with the network tab capturing and it shows that the result was aborted: here
Thanks #ArunPJohny, this has given me a new direction to look in. Is there some kind of "onAbort" ajax callback? As I would have thought this kind of response would be caught by the "error:" callback
Update 2:
I have since found my way to a number of SO topics, more notably: xmlhttprequest timeout / abort not working as expected?
Tim provides some useful links for catching the abort, but still no clue as to why its getting aborted.
follow-on: here

Categories

Resources