Value of variable outside $.get call not been set [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I am trying to set the value of a variable from inside a $.get jquery call but it is not working. Below is my code
var uData = [];
$('#tfriends').click(function () {
get_json(function () {
alert(uData);
});
});
function get_json(callback) {
$.get('url', function (data) {
var data = $.map(data.result, function (obj) {
obj.Id = obj.Id || obj.name;
obj.text = obj.text || obj.name;
return obj;
}, "json");
uData = data;
});
}

You are not calling your callback function inside the $.get function. Check the comment below.
var uData = [];
$('#tfriends').click(function () {
get_json(function () {
alert(uData);
});
});
function get_json(callback) {
$.get('url', function (data) {
var data = $.map(data.result, function (obj) {
obj.Id = obj.Id || obj.name;
obj.text = obj.text || obj.name;
return obj;
}, "json");
uData = data;
callback() // this line will actually call your callback function
});
}
Edit
As #FelixKling suggested below, you can pass the data in the callback itself rather than declaring a global variable as so
// var uData = [];
$('#tfriends').click(function () {
get_json(function (returned_data) {
alert(returned_data);
});
});
function get_json(callback) {
$.get('url', function (data) {
var data = $.map(data.result, function (obj) {
obj.Id = obj.Id || obj.name;
obj.text = obj.text || obj.name;
return obj;
}, "json");
//uData = data;
callback(data) // this line will actually call your callback function
});
}

This would (IMHO) be better with Promises, abstracting the retrieval of the resource, from the pre-processing, and then from the subsequent application layer handling:
// resource retrieval
function get_json() {
return $.get('url');
}
// pre processing
function preprocess(data) {
// no need to use `.map` since you're modifying the data in-place
data.result.forEach(function(obj) {
obj.Id = obj.Id || obj.name;
obj.text = obj.text || obj.name;
});
return data.result;
}
// chaining it all together
get_json().then(preprocess).then(callback);
If the pre-process stage is always required then it would be acceptable to incorporate that in get_json:
function get_json() {
return $.get('url').then(preprocess);
}

Related

Javascript & knockoutjs: how to refactor the following code to be able to access the properties outside the function

Im struggling to find a way to get the properties Override & Justification available outside of the function. The code is:
self.CasOverridesViewModel = ko.observable(self.CasOverridesViewModel);
var hasOverrides = typeof self.CasOverridesViewModel === typeof(Function);
if (hasOverrides) {
self.setupOverrides = function() {
var extendViewModel = function(obj, extend) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
extend(obj[property]);
}
}
};
extendViewModel(self.CasOverridesViewModel(), function(item) {
item.isOverrideFilledIn = ko.computed( function() {
var result = false;
if (!!item.Override()) {
result = true;
}
return result;
});
if (item) {
item.isJustificationMissing = ko.computed(function() {
var override = item.Override();
var result = false;
if (!!override) {
result = !item.hasAtleastNineWords();
}
return result;
});
item.hasAtleastNineWords = ko.computed(function() {
var justification = item.Justification(),
moreThanNineWords = false;
if (justification != null) {
moreThanNineWords = justification.trim().split(/\s+/).length > 9;
}
return moreThanNineWords;
});
item.isValid = ko.computed(function() {
return (!item.isJustificationMissing());
});
}
});
}();
}
I've tried it by setting up a global variable like:
var item;
or
var obj;
if(hasOverrides) {...
So the thing that gets me the most that im not able to grasp how the connection is made
between the underlying model CasOverridesviewModel. As i assumed that self.CasOverridesViewModel.Override() would be able to fetch the data that is written on the screen.
Another try i did was var override = ko.observable(self.CasOverridesViewModel.Override()), which led to js typeError as you cannot read from an undefined object.
So if anyone is able to give me some guidance on how to get the fields from an input field available outside of this function. It would be deeply appreciated.
If I need to clarify some aspects do not hesitate to ask.
The upmost gratitude!
not sure how far outside you wanted to go with your variable but if you just define your global var at root level but only add to it at the moment your inner variable gets a value, you won't get the error of setting undefined.
var root = {
override: ko.observable()
};
root.override.subscribe((val) => console.log(val));
var ViewModel = function () {
var self = this;
self.override = ko.observable();
self.override.subscribe((val) => root.override(val));
self.load = function () {
self.override(true);
};
self.load();
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Passing an array to another function in ReactJS

Simpleish react question that is evading me for a second:
readData: function(){
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
return envUsersArray;
});
console.log(envUsersArray, 'hey');
},
anotherfunc: function(){
}
I have this function and I want to return envUsersArray and use it wherever. Obviously at the moment it is returning a blank array as the readData function is not in the scope of the snapshot function.
How can I pass it down to the readData function and then use it inside another function such as anotherfunc
I know I probably need to call this. somewhere but the logic isn't quite coming to me at the mo
I'd suggest using Promises.
readData: function(){
return new Promise(function(resolve) {
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
resolve(envUsersArray);
});
});
},
anotherfunc: function(){
this.readData().then(function(arr) {
//do stuff here
});
}
You may return a promise that will resolve with value that is retrieved asynchronously:
readData: function() {
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
return new Promise(function(success) {
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
success(envUsersArray);
}
});
},
anotherfunc: function(){
this.readData().then(function(result) {
console.log(result);
});
}

How to add value to an object from a function

I have an object like the one
var obj = {
key : firstLevel()
}
Now I want the value of obj.key to be returned from a function say firstLevel().
The issue in my case is that, the firstLevel() function embeds a callback function. And I want to return the response from it as the value for obj.key.
The function definition is as follows
var firstLevel = function(){
esClient.search(function(response){
console.log(response); //I want to return this response as the value for obj.key
})
}
var firstLevel = function(){
var res;
esClient.search(function(response){
console.log(response); //I want to return this response as the value for obj.key
res = response;
});
while(!res) {}
return res;
}
this will work, but it will freeze your window.
var firstLevel = function(){
var result;
esClient.search(function(response){
result=response;
})
return result;
}

jquery making correct callback

how to correctly make callback in jquery plugin.
(function($) {
var parameter = {
first:'1',
second:'2',
call: $.noop
};
var something = 'yes';
var testf = function(){
// i neeed launch callback here;
var something_else = something + 'no';
alert(something_else)
}
$.fn.sadstory = function(options) {
if (options && typeof options === 'object')
{
$.extend(parameter, options);
}
testf();
return this;
}
})(jQuery);
and i need atccess var and owerwrite or making somthing else with him.
$('elm').sadstory({
call: function(){
this.something = 'no';
}
});
and result would by alert box with text nono instead of yesno, now to make this callback correctly.
i think you can do it like that:
$.fn.sadstory = function(options,callback) {
if (options && typeof options === 'object')
{
$.extend(parameter, options);
}
testf();
// example, var c is passed to callback function
var c= "abc";
callback(c);
return this;
}
you can call like
.sadstory({..},function(c) {
console.log(c) // logs "abc"
})
should also work as property of options
this.something doesn't exist. The only something is a variable with the scope of your testf method.
A solution is to pass an object as a parameter to the callback, and allow the callback to modify this object.
(function($) {
var parameter = {
first:'1',
second:'2',
call: $.noop
};
var something = 'yes';
var testf = function(){
// Initialize the string to a default value
var stringGenerationParams = { something: 'yes' };
// Allow the callback to modify the string generation params
parameter.call(stringGenerationParams);
// At this point, stringGenerationParams.something may have been
// modified by the callback function
var something_else = stringGenerationParams.something + 'no';
alert(something_else)
}
$.fn.sadstory = function(options) {
if (options && typeof options === 'object')
{
$.extend(parameter, options);
}
testf();
return this;
}
})(jQuery);
And now, this will work:
$('elm').sadstory({
call: function(e) {
e.something = 'no';
}
});

Resolve function pointer in $(document).ready(function(){}); by json string name

I have a json object retrieved from server in my $(document).ready(...); that has an string that I would like to resolve to a function also defined within $(document).ready(...); so, for example:
$(document).ready(function{
$.getJSON(/*blah*/,function(data){/*more blah*/});
function doAdd(left,right) {
return left+right;
}
function doSub(left,right) {
return left-right;
}
});
with json string:
{"doAdd":{"left":10,"right":20}}
One way I thought about was creating an associative array of the function before loading the json:
var assocArray=...;
assocArray['doAdd'] = doAdd;
assocArray['doSub'] = doSub;
Using eval or window[](); are no good as the function may not be called for some time, basically I want to link/resolve but not execute yet.
Change your JSON to
{method: "doAdd", parameters : {"left":10,"right":20}}
Then do
var method = eval(json.method);
// This doesn't call it. Just gets the pointer
Or (haven't tried this)
var method = this[json.method]
How about something like this?
$(function(){
// Function to be called at later date
var ressolvedFunc = null;
// Ajax call
$.getJSON(/*blah*/,function(data){
// Generate one function from another
ressolvedFunc = (function(data) {
var innerFunc;
var left = data.left;
var right = data.right;
// Detect action
for (action in data) {
if (action == "doAdd")
innerFunc = function() {
return left + right;
};
else
innerFunc = function() {
return left - right;
};
}
return innerFunc;
})(data);
});
});
The anonymous function returns fresh function, with the new values stored within the enclosure. This should allow you to call the function at later date with the data previously retrieved from the GET request.
Rich
try this:
var doX = (function() {
var
data = [],
getDo = function(action) {
for(var d in data) {
if (data[d][action]) {
return data[d];
}
}
return null;
};
return {
set: function(sdata) {
data.push(sdata);
},
doAdd: function() {
var add = getDo("doAdd");
if (!add)
return 0;
return add.doAdd.left + add.doAdd.right;
},
doSub: function() {
var sub = getDo("doSub");
if (!sub)
return 0;
return sub.doAdd.left + sub.doAdd.right;
}
};
})();
$(document).ready(function{
$.getJSON(/*blah*/,function(data){ doX.set(data); });
});

Categories