Appcelerator. Get data from request out of onload function - appcelerator

I am working with Appcelerator Titanium and I am making requests to a remote API.
I need to get the results of a request out of the onload function and into another calling function. The request call is located in a function of its own in another file that is included in the main .js file.
This is my code: http://pastie.org/1731674
How can it be altered to do this?

Modify loadPhones() to accept a callback that accepts the output as a parameter
function loadPhones( callback ) {
(...)
xhr.onload = function() {
(...)
if ( 'function' == typeof callback ) {
callback(output);
}
}
(...)
}
And then, in app.js or wherever you call loadPhones() from
loadPhones( function( data ) {
// do whatever with data
});

Related

unable to pull data from browser.storage.local.get

trying to implement options page for a firefox addon/extension version 64.0. I am using browser.storage.local.set to store data. but when I use browser.storage.local.get to pull the data, the result is <unavailable> on the console log.
the following is the function i run in my options.js file (i entered njnj on the form field gateway and hit the submit button)
function saveOptions(e) {
e.preventDefault();
console.log("you are here")
console.log(document.querySelector("#gateway").value)
browser.storage.local.set({
"gateway": document.querySelector("#gateway").value });
console.log(browser.storage.local.get("gateway"))
}
document.querySelector("form").addEventListener("submit", saveOptions);
my actual output in the console log is as follows :
you are here options.js:4:3
njnj options.js:5:3
<unavailable> options.js:8:3
ok so I did figure out partly why the above code is not working. the problem is that browser.storage.local.get() returns a 'promise' in javascript (I dont actually know what it means yet). So you have to have a code that will actually retrieve the answer/saved value from this 'promise'. I will give you an example on how to retrieve the value:
// first save a key value pair into storage
browser.storage.local.set({"key": 'value'})
// to retrieve this value, first declare a new variable
var savedvalue = "zero"
// retrieve the 'promise' of key value pair, then run the associated function to get
//the savedvalue and set it equal to previously declared variable.
browser.storage.local.get(['key'], function(result) {savedvalue = result.key});
// now, when you call savedvalue (even outside the function above), it will return 'value'
console.log(savedvalue)
output>> value
You could use async function and await, like this
async function saveOptions(e) {
e.preventDefault();
await browser.storage.local.set(
{ "gateway": document.querySelector("#gateway").value }
);
}
document.querySelector("form").addEventListener("submit", async saveOptions);
You don't need to pass the 'e' to the function, you're not doing anything with it.
You could also refactor it this way, if the mood took you
document.querySelector("form").addEventListener( "submit", async ()=> {
e.preventDefault();
await browser.storage.local.set(
{ "gateway": document.querySelector("#gateway").value }
);
});
The question is really about how to get/handle the value of a Promise in async Javascript (which the browser.storage.local.get() method is).
browser.storage.local.get('gateway').then(
function (result) {
// code goes here
console.log(result.gateway);
}).catch(function (error) {
// error code
});
see How can I access the value of a promise?

How to avoid loop in Ajax call

I have function getData() which make an ajax call and retrive JSON data. On success i call another function which is marquee() . inside marquee on finish event i call getData() again, But each time getData() when get called, it increases it's request to mentioned file data.php, For example on first call it call once, Second call it request twice, and then twice become 4times,8times and more and more, how to avoid this?!
function getData()
{
$.get('data.php).done(function(response)
{
var data = JSON.parse(response);
if(data.Direction == "left")
{
$(".marquee").html("<span data-direction='"+data.Direction+"'>"+data.Message+"</span>");
}else if(data.Direction == "right"){
$(".marquee").html("<span data- direction='"+data.Direction+"'>"+data.Message+"</span>");
}
});
}
function marquee()
{
$(".marquee").marquee({duration : 10000}).bind("finished",function()
{
getData();
});
}
I hope i was clear... Appreciate each answer.
Every time you are calling marquee function, you are basically binding an event finished on to it. On multiple such function calls, you will have duplicate events. In your code setup, you need to unbind the function before binding it. Something like
$(".marquee").marquee({duration : 10000}).unbind("finished",getData).bind("finished",getData)
Ideally, you should bind only once so you do not have to unbind it again and again.

Returning results of d3 request from amd module / requirejs

I'm trying to create a amd module that runs a d3 request (d3.json() in this case) and returns the data from the request. I can't seem to figure out how to make the module wait for the request to finish before it returns the data. As a result I keep getting undefined in my main program when I try to access the data.
define(['app/args'], function(args){
d3.json("resources/waterData.php?stn=" + args.stationID, function (error, data) {
var dataToReturn = {};
//Do some stuff with data
return dataToReturn;
});
});
That is the basic structure of what I'm trying to do. I think the main issue is that the 2nd argument in d3.json is a callback for when the data is loaded, so when I try to return the data, it isn't getting outside the module. I haven't been able to figure out how to get the data from the callback to return it outside the module.
The real issue is that the d3.json function is asynchronous, so you can't just return the processed data from the outside function directly. One way you can work around this is by returning a promise rather than the data itself. You can use the d3.json callback to resolve the promise, and then other modules which depend on the data can register their own callbacks which will run once that promise has been resolved.
For example, if you use jQuery's $.Deferred() you can do the following:
define(['app/args', 'jquery'], function(args, $){
// CREATE DEFERRED OBJECT
var deferred = $.Deferred();
d3.json("resources/waterData.php?stn=" + args.stationID, function (error, data) {
var dataToReturn = {};
//Do some stuff with data
// RESOLVE NOW THAT THE DATA IS READY
deferred.resolve(dataToReturn);
});
// RETURN THE PROMISE
return deferred.promise();
});
Then when you want to use the data, you can require the above module, and register a listener that will fire once the data is ready:
require(['nameOfYourModuleAbove'], function(deferred) {
deferred.done(function(data) {
// DO SOMETHING WITH YOUR DATA
});
})

AJAX + jQuery Deferred: execution sequence

Task: get data from server with $.post, process them by method .success(), after that call some function.
var t;
$.when($.post("get_json.php", function(res) {
t = res;
}, 'json')).done(function() {
console.log(t);
});
Do I understand correctly that the Deferred method .done() is executed after .success is done (ie t = res)?
But why "console.log(t)" shows "undefined"?
Is .done() fires after request, but before .success()?
Passing a "success" callback to $.post() is an alternative to the (preferred) chaining of .done(...). Do one or the other, not both, then you don't need to worry about the execution order.
Also, unless you have a decent caching strategy for async data, you shouldn't be setting t as an outer var.
$.post("get_json.php", ...).done(function(t) {
console.log(t);
//do awesome things with t here
});
Caching would be something like this :
var asyncCache = {};
...
function get_t() {
return (asyncCache.t) ? $.when(asyncCache.t) : $.post("get_json.php", ...).done(function(t) {
asyncCache.t = t;
});
}
...
get_t().done(function(t) {
console.log(t);
//do awesome things with t here
}
$.when() is ONLY needed when you have multiple promises and you want to wait for all of them to complete. You simply don't need it at all for your single ajax call. You can just do it like this:
$.post("get_json.php").done(function(t) {
// use the results of the ajax call here
console.log(t);
});
In addition, your code example was using BOTH a success callback function AND a .done() handler. Pick one of the other, not both as they are different ways of getting a callback when the ajax call is done. I'd suggest the promise implementation above because it's more flexible. But, you could also use just the success handler:
$.post("get_json.php", function(t) {
// use the results of the ajax call here
console.log(t);
}, 'json');
Note, when you have an asynchronous operation like this, you need to consume the results of the ajax call in the success callback (or the promise callback) or call some function from there and pass it the data. You do not want to put the data into a global variable or a variable in a higher scope because other code will simply have no way of knowing when the data is ready and when it is not. Put your action in the callback.
If you have more than one ajax call that you want to wait for, then you can do it like this:
$.when($.post("get_json.php"), $.post("get_json2.php")).done(function(r1, r2) {
// use the results of the ajax call here
console.log(r1[0]); // results from first ajax call
console.log(r2[0]); // results from second ajax call
});

Jasmine use it to over ride and test a method that uses aiax

I have a JS file that contains many methods, ajax caller is constant.
function ajaxCaller(data,url,callback) { //standard jquery ajax call here }
function method1(){
// ... does work ... then
ajaxCaller(data,url,function(){ // changes the dom } );
}
How can I use jasmine to over ride the ajaxCaller method that is being called by nearly every method in my js file such that I can test that the DOM is getting changed?
Probably you have something like the code below, right?
function ajaxCaller(data, url, callback) {
$.ajax(url, { data: data, success: callback });
}
In this case you can mock the jQuery ajax method so that instead of real AJAX request the function you provide will be called. It is possible to define the response you want to be "returned from the server". Jasmine andCallFake function will do it for you:
it ('when some response returned from the server, something happens', function() {
var response = {}; // ... define the response you need
spyOn($, 'ajax').andCallFake(function(url, options) {
options.success(response);
});
method1();
// and assert that something really happens ...
});

Resources