Javascript not returning data to AS3 flash - javascript

I am hoping someone can help me. I have the following function in FlashBuilder 4 using AS3:
protected function doIt():void
{
if (ExternalInterface.available) {
var retData:String;
retData = ExternalInterface.call("returndata");
if(retData != null) {
eidLbl.text = retData.toString();
} else {
eidLbl.text = "Returned Null";
}
} else {
eidLbl.text = "External Interface not available";
}
}
and the following javascript function it calls:
var fql_query = "some query format";
function returndata(){
return fql_query;
}
When I run these from my site everything works fine! The flash file calls the javascript function and returns "some query format" into the proper text field.
However if I change my flash function to be as follows:
protected function doIt():void
{
if (ExternalInterface.available) {
var retData:String;
retData = ExternalInterface.call("runFQL",uidLbl.text);
if(retData != null) {
eidLbl.text = retData.toString();
} else {
eidLbl.text = "Returned Null";
}
} else {
eidLbl.text = "External Interface not available";
}
}
and the following javascript function:
function runFQL(id){
var user_id = id;
var page_id = "**********"; // the page id that is actually there is valid
var fql_query = "SELECT uid FROM page_fan WHERE page_id="+page_id+" and uid="+user_id;
FB.api({
method: 'fql.query',
query: fql_query
},
function(response){
if (response[0]) {
var uid = response[0].uid;
window.alert(uid); //100001632043058
return uid;
} else {
window.alert("return 1000");
}
});
};
My problem is that when I run this one, it passes the id in, runs the query, and accurately pulls back the uid and displays it in the alert BUT (AND HERE IS MY PROBLEM) it won't pass it back to flash in the return. It comes back as null or undefined each time.
Can anyone tell me what I am missing. I have been scouring google for hours.

function(response){
if (response[0]) {
var uid = response[0].uid;
window.alert(uid); //100001632043058
return uid;
} else {
window.alert("return 1000");
}
});
Is called when the FB.api function completes not when you call runFQL. So runFQL runs through and returns undefined everytime.
What you can do is once the FB.api call completes call a function inside the flash app and pass the return value there. So basically do a ExternalInterface.addCallback in flash and call that function from javascript.
function runFQL(id){
var user_id = id;
var page_id = "**********"; // the page id that is actually there is valid
var fql_query = "SELECT uid FROM page_fan WHERE page_id="+page_id+" and uid="+user_id;
FB.api({
method: 'fql.query',
query: fql_query
},
function(response){
if (response[0]) {
var uid = response[0].uid;
window.alert(uid); //100001632043058
// needs ExternalInterface.addCallback("sendDataBack",handleData); in your
// as3 code
yourSwf.sendDataBack(uid);
} else {
window.alert("return 1000");
}
});
};

You have a very small work flow issue. In your JavaScript code you are calling FB api and then the function ends, in which case it will return a undefined since nothing is returned. But you are thinking that the nameless function is what does the return when actually it isn't even called yet because the API didn't even get a response.
What you need to do is change the following line of code.
return uid;
to
myHTMLFlashObject.someFunctionName(uid);
and in your flash project you need to add a function someFunctionName and add it as an ExternalInterface callback function.
Remember APIs are not asynchronous so you can expect the function runFQL to return undefined long before the API as sent a response.

Related

Codeigniter, Vanilla JS: Sending Ajax post request but not recieving any data in php

Good Day Everyone
I have a little problem with sending and recieving post data with ajax. I'm not new to this matter. I just recently started using the codeigniter framework, and now, the pattern I have always used for ajax doesn't work anymore. (Never used a 'foreign' framework before, but my own)
I hope you can help me.
The main problem is, that the php controller doesn't recieve the post data.
ajax.js (ajax handling, AJAX_URL is 'http://localhost/ajax/process' at the moment of th call, I already checked that):
function AjaxRequest(callback, data) {
this.data = (data!== undefined) ? data : [];
this.callback = callback;
this.request = new XMLHttpRequest();
this.addData = function(key, value) {
this.data[key] = value;
};
this.send = function() {
var callback = this.callback;
this.request.open('POST', <b>AJAX_URL</b>, true);
this.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
this.request.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
callback(this.responseXML);
}
};
var data = this.createPostData();
this.request.send(data);
};
this.createPostData = function() {
var data = '';
for (var key in this.data) {
data += key + '=' + this.data[key] + '&';
}
data = data.slice(0, -1);
console.log(data);
};
}
actions.js (contains action handling from website):
function requestLogin() {
var username = $("input#txtUsername").val();
var password = $("input#txtPassword").val();
var request = new AjaxRequest(callbackLogin);
request.addData('action' , 'login_user');
request.addData('username', username);
request.addData('password', password);
request.send();
}
function callbackLogin(xml) {
console.log(xml);
}
Ajax.php (CI_Controller for ajax request handling):
class Ajax extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->library('session');
$this->load->model('user_model');
}
public function process() {
$data = $this->input->post();
$action = $data['action'];
if (method_exists($this, $action)) {
$this->$action($data);
}
}
public function login_user($data) {
$passwd_enc = md5($data['password']);
$xml_resp = new Xml_response();
$user = $this->user_model->login_user($data['username'], $passwd_enc);
$xml_resp->start();
if (!$user) {
$xml_resp->error();
$xml_resp->send_message(Xml_message::ERROR, 'Benutzername oder Kennwort ist inkorrekt.');
} else {
$xml_resp->success();
$xml_resp->send_message(Xml_message::SUCCESS, 'Sie wurden erfolgreich angemeldet.');
$xml_resp->send_data('user', $user);
}
$xml_resp->end();
}
}
Now when I try to send the request, the method process is called (checked through logging) but the post array is empty (in each possibility: $_POST or codeigniter's own post array) and I recieve a responseXML which is null.
Is there anything I have done wrong in this part or do I have to consider something else when using codeigniter?
Thank you very much in advance and please don't be shocked by my bad english (I come from Switzerland ;)
Best Regards, Tobias Widner
Try adding a slash at the end of your request URL. I don't know if your codeigniter configuration is the same as mine but if I don't put a slash at the end of the URL, my .htaccess redirects to the URL with a slash on. This redirect removes any post data.

Ajax call on $.ajax().complete

I have a problem with jQuery ajax function. I working with API that provides users and RBAC managment. By design this is separated functions, so when i create a user and assign a role for it i should call two requests - first i send 'create user' and it's return a {"success":"true", "id":"[id nuber]"} then i send 'assign role' with params like "{"item":"RoleName", "user_id":"[id from previous request]"}".
There is object "api" which have some methods for work with API. It is a simple wrapper which knocking on www.myurl.api/ and returns json. Because of it may take a long time api object methods takes a handlers that will be run on success and fail. If api now running a request then api.ready == false, otherwise api.aready == true. Result of last request stored in api.data as object.
Problem is that result not saved in api.data in case when two API request cascaded, like:
api.send(params, //params is json for user creation
function(){ //handler on this request result
... //creating another parms for assignment from api.data
api.send(params2, function(){//handler that works if api coorectly creates a new user
... //here i try send a request with params and it fails
})
}
);
code of api.send method:
send: function (entity, request, params, method, handler){
if (!method)
method='POST';
if (request.toLowerCase()=='get')
request = '';
if (request)
request += '-';
api.data = null;
params.apiKey = api.key;
api.ready = false;
api.handler = handler;
$.ajax({
url: this.url+request+ entity,
method: 'GET',
data: params
}).complete(function(msg) {
api.data = JSON.parse(msg.responseText);
if (api.data[0] && api.data[0].meta)
api.data.forEach(function (element, index, array){
element.meta = JSON.parse(element.meta)
});
api.ready = true;
api.handler.call();
});
}
and this is function that calls to create new user
function createUser(){
validateCreateForm();
if (!createValidated )
return;
var values = {
"username": $('#inputUsername').val(),
"password": $('#inputPassword').val(),
"comment": "Added by "+adderUsername
};
api.send('users','add', values, 'POST', function () {
if (api.data.success="true"){
//===========all in this if works ONLY if api works succesfully
//===========and api.data.id is exist and correct
message("success", "Was created username " + values.username);
$('#inputUsername').val('');
$('#inputPassword').val('');
//==========Problem is here
id = api.data.id; //in this var stores id
console.log('api.data.id is ' + id);//undefined, should be some int.
//if write something like id=42 rights will be correcttly assigned for user with id 42
//================================================================
if (!$('#inputRole').val())
return;
api.send('assignments',
'add',
{
"user_id": id,
"item_name": $('#inputRole').val()
},
'POST',
function () {
if (api.data.success="true"){
message("success", "Account was created and permissions granted");
}
else {
message("success", "Inner error. Please, try again later.");
}
}
);
}
else {
message("danger", "Inner error. Please, try again later.");
}
);
}

JavaScript not getting function returns in Node.js

I have made an IRC bot for purely learning purposes but I have a Minecraft server that I use an API to get the status back as JSON. Now I have made the code and it works but for some reason when I try and use a return on the function so I can get the content it seems to not work?
So I have the two functions below:
function getservers(name) {
if (name == "proxy") {
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
return data.motd;
});
} else if (name == "creative") {
var Request = unirest.get(creative);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
return data;
});
} else if (name == "survival") {
var Request = unirest.get(survival);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
return data;
});
}
}
// Main logic:
function parsemessage(msg, to) {
// Execute files
function pu(o,t,f){if(o)throw o;if(f)throw f;bot.say(to,t)}
if (msg.substring(0,1) == pre) {
// Get array
msgs = msg.split(' ');
console.log(msgs[0]);
// Run Login
if (msgs[0] == pre+"help") {
bot.say(to, "Help & Commands can be found here: https://server.dannysmc.com/bots.html");
} else if (msgs[0] == pre+"status") {
// Get status of server, should return online/offline - player count for each server - motd
server = getservers("proxy");
console.log(server);
/*var data = '';
var Request = unirest.get('https://mcapi.us/server/status?ip=185.38.149.35&port=25578');
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
});
} else if (msgs[0] == pre+"players") {
// Should return the player list for each server
} else if (msgs[0] == pre+"motd") {
// Should return the message of the day.
} else if (msgs[0] == pre+"ip") {
bot.say(to, "ShinexusUK IP Address: shinexusuk.nitrous.it");
} else if (msgs[0] == pre+"rules") {
}
}
}
The code in the getservers() function works, when I do the
console.log(data["motd"]);
It outputs my servers message of the day. But when I do return
data.motd
(same as data["motd"]?) The code that calls the function is here
server = getservers("proxy");
console.log(server);
Please note this is a node.js code and it contains many files so i can't exactly paste it. So here is the link to the github repo with the whole node application: Here
When the function getservers is called, it makes an asynchronous request and return nothing.
Then the callback is fired with the response of that request as parameter.
Note that the function getservers will end before the end callback of your request is called
(simplified version)
function getservers(name) {
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
return data.motd;
});
// nothing returned here
}
What you need is a function callback that will be called after you got the response.
function getservers(name, callback) { // callback added
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
callback(data.motd); // fire the callback with the data as parameter
});
// nothing returned here
}
And then you can use your function like this :
getservers("proxy", function(server){
console.log(server);
....
})

Uncaught TypeError: undefined is not a function for request() in Titanium

I have a problem with 1 of my functions.
in app.js ia have th following:
//Including all functions
Ti.include('functions.js');
//Including the login screen
Ti.include('login.js');
//Including the register screen
Ti.include('register.js');
So all the functions are above the other files that could call a function.
In login.js I have the following code:
//'login' is the type
var request = request('login', loginUsernameInput.value, md5(loginPasswordInput.value));
Ti.API.info('request: ' + request);
if(request == true) {
alert('You are loggedin');
} else {
alert('Something went wrong');
}
The request function looks like this:
function request(type, username, password) {
//Database connection
var db = Ti.Network.createHTTPClient();
db.open('POST', 'http://myip/mobile_app/');
Ti.API.info('type: ' + type);
Ti.API.info('username: ' + username);
Ti.API.info('password: ' + password);
//If variables has been send
db.onload = function() {
var answer = this.responseText;
Ti.API.info('type answer: ' + typeof this.responseText);
if(answer == 'true') {
Ti.API.info('TEST');
return true;
} else {
return false;
}
};
//Variables to send
db.send({
type: type,
username: username,
password: md5(password)
});
//If there is an error
db.onerror = function(e) {
Ti.API.info('error: ' + JSON.stringify(e));
};
}
I know that this.responseText returns true and that the function md5() works aswell.
I know this because I also tested login.js when the code is like:
Ti.API.info('request: ' + request('login', loginUsernameInput.value, md5(loginPasswordInput.value)));
if(request('login', loginUsernameInput.value, md5(loginPasswordInput.value)) == true) {
alert('You are loggedin');
} else {
alert('Something went wrong');
}
The above also returns that function request() is undefined
So as soon as try to login I get the following error:
So my question is how can resolve the error?
I think the issue is that you redefine variable request to the return value of function request. You request function does not return anything. Therefore it returns undefined.
Now that you set request to undefined. You cannot use request() anymore, because you overwrote it.
Attempting to call an undefined value as a function, results in undefined is not a function
See demonstration: http://repl.it/UXE/1
Indeed, #Gabs00 is right when he says that you're redefining your request variable.
But the real question is how could you have avoid this problem ?
And the answer is in the way you're coding. By using Ti.include, you're not using the best practices recommended by Titanium.
Instead, you should do something like this :
In a file models/User.js :
exports.request = function(type, username, password) {
// Your code here
};
Then, instead of writing (in your app.js file) :
Ti.include('functions.js');
var request = request('login', loginUsernameInput.value, md5(loginPasswordInput.value));
You'll have :
var User = require('models/User');
User.request('login', loginUsernameInput.value, md5(loginPasswordInput.value));
But even with this code, it's sot satisfying enough...
What you should probably try is to declare as many functions as your requests. Even if your code is common for your 2 requests for now, I can assure you that it won't be that way very long.
Thus, there is the final code I recommend :
In your models/User.js file :
function request(type, username, password) {
// Your code
};
exports.login = function(username, password) {
request('login', username, password);
};
exports.register = function(username, password) {
request('register', username, password);
};
The cool thing with this code is that your request method is totally protected: the only code which can access this function is the one written in your models/User.js file. For the others, it's like this function doesn't even exist.
In you app.js file :
var User = require('models/User');
User.login(loginUsernameInput.value, md5(loginPasswordInput.value));
I think it's more readable this way, don't you?
If you want more information about this pattern, you should probably read these articles:
CommonJS modules
Titanium best practices
As you'll see, you should reuse this pattern for your windows too (your Ti.include('login.js'); and Ti.include('register.js');)
This question got answered here: http://developer.appcelerator.com/question/175412/function-not-returning-anything#280011
Edit:
In User.js:
function request(type, username, password, callback) {
db.onload = function() {
Ti.API.info('type antwoord: ' + typeof this.responseText);
callback( this.responseText );
};
}
exports.login = function(username, password, callback) {
request('login', username, password, callback);
};
and in login.js:
// last parameter is the callback function
User.login(loginUsernameInput.value, md5(loginPasswordInput.value), function(response){
Ti.API.info('login response: ' + response)
});
now i get true or false as response.

about java script variable scope and facebook api

I am using facebook login api to get user information, code can exceed correctly and FirstName can get from facebook api, but the first alert has correct value, the second value is still "". First I think it is because remote call time cause the second alert is before the first alert, after I using a delay function before second alert, also I can not get value in the second alert.
Part of code like below.
if (response.status === 'connected') {
FirstName="";
LastName="";
FB.api('/me', function(response) {
FirstName = response.first_name;
LastName = response.last_name;
Email = response.email;
alert(FirstName);
});
alert(FirstName);
}
FB.Api is asynchronies method, which will post/get to a remote server.
The execution don’t wait for it to finish before your second “alert”
The only way you can be sure your FirstName is initialized, is using callbacks or MVVM pattern.
Here MVVM with knockout.js code:
var fbModel = function () {
var self = this;
self.FirstName = ko.observable("");
self.FirstName.subscribe(function () {
//DO what you want, first name just been changed from FB
});
self.load = function () {
FB.api('/me', function (response) {
self.FirstName(response.first_name); // WILL TRIGGER self.FirstName.subscribe
});
};
};
And don’t forget, applying this model is easy, I can give you some links if you want. (But just go and look on examples on their site)
Edit : callback version
var FirstName = ""; // Global
function callback(name) {
//your name has been loaded
FirstName = name; // Global is initialized
};
function load (callback) {
FB.api('/me', function (response) {
callback(response.first_name);
});
};
//Now just call the load :
load(callback);

Categories