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;
}
Related
I have n number of functions, each one takes a 'data' {Object} as argument. Each function return a {Boolean} based on the given argument.
I want to compose/chain these functions, what is the best way to accomplish that?
See code below.
var fn1 = function(data) {
return data.status === 404;
};
var fn2 = function(data) {
return data.url === 'any_url';
};
var composed = compose(fn1, fn2);
// The line below must return false:
composed({ status: 404, url: 'foobar'});
// The line below must return true:
composed({ status: 404, url: 'any_url'});
So you want to return true if all functions return true? That can be achieved with Array#every. We simply use Array#every on the array of functions and return the function's result in the callback:
function compose() {
var fns = Array.prototype.slice.call(arguments);
return function(obj) {
return fns.every(function(f) {
return f(obj);
});
};
}
function compose() {
var fns = Array.prototype.slice.call(arguments);
return function(obj) {
return fns.every(function(f) {
return f(obj);
});
};
}
var fn1 = function(data) {
return data.status === 404;
};
var fn2 = function(data) {
return data.url === 'any_url';
};
var composed = compose(fn1, fn2);
// The line below must return false:
console.log(composed({
status: 404,
url: 'foobar'
}));
// The line below must return true:
console.log(composed({
status: 404,
url: 'any_url'
}));
The advantage of this is that Array#every will stop as soon as one return value is false.
With ES6+:
function compose(...fns) {
return obj => fns.every(f => f(obj));
}
Note: compose is a poor choice of name for this because "composing functions" usually refers to passing the result of one function into the other function. I.e. compose(f, g)(x) would be the same as f(g(x)).
you could do something as simple as
function compose(data){
return fn1(data) && fn2(data)
}
this function will return true if all conditions(return values of your functions) are true
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);
}
I write my custom AngularJS filter, which should transform id to name, which will get from IndexedDb.
I wrote this filter:
cardsList.filter('getCollectionName', ['IndexedDb', function(IndexedDb) {
return function(idCollection) {
var val = 'not';
IndexedDb.getById(IndexedDb.STORES.COLLECTION_STORE, idCollection).then(function(data) {
val = data.name; //here dont work return data.name;
}, function(err){
$window.alert(err);
});
return val; // here is still 'not'
}; }]);
So i have property val and i want set it with name of collection by id. But its return initial value 'not'.
I knew that inside calling is not visible property val. But return data.name; inside succesful callback dont work.
I looked at How do I return the response from an asynchronous call?, but I dont understood how fix my problem.
How can I fix this so function return data.name from callback? Thanx
You can use $q service of the angularjs.
Return the value when your promise resolves in $q.all(..)
cardsList.filter('getCollectionName', ['IndexedDb','$q', function(IndexedDb,$q) {
return function(idCollection) {
var val = 'not';
var promises=[];
promises.push(IndexedDb.getById(IndexedDb.STORES.COLLECTION_STORE,idCollection).then(function(data) {
val = data.name; //here dont work return data.name;
}, function(err){
$window.alert(err);
})
);
$q.all(promises).then(function(){return val;});
}; }]);
I have two objects
function Response(dbResponseId, responseText){
this.response = {
"dbResponseId" : dbResponseId,
"responseText" : responseText,
"isDeleted" : false,
};
this.setResponseText = function(responseText){
this.response.responseText = responseText;
return this.response;
};
this.getId = function(){
return this.response.frontEndId;
};
this.deleted = function(){
this.response.isDeleted = true;
};
return this.response;
}
function OptionGroup(responses, dbOptionGroupId,isDeleted,id){
this.optionGroup = {"dbOptionGroupId" : dbOptionGroupId, "responses" : responses, "isDeleted" : isDeleted,"frontEndId" : id};
this.setResponses = function(responses){
this.optionGroup.responses = responses;
return this.optionGroup;
};
this.addResponse = function(response){
this.optionGroup.responses.push(response);
return this.optionGroup;
};
this.getId = function(){
return this.optionGroup.frontEndId;
};
this.setId = function(id){
this.optionGroup.frontEndId = id;
return this.optionGroup;
};
this.deleted = function(){
this.optionGroup.isDeleted = true;
return this.optionGroup;
};
this.getResponsesById = function(id){
for(var i = 0; i < this.optionGroup.responses.length;i++){
if(id == this.optionGroup.responses[i].getId()){
return this.optionGroup.responses[i];
}
}
return null;
};
return this.optionGroup;
}
However, when I try and call any of the functions that I've created, console tells me that said object does not have such a function. When I print out a Response or OptionGroup object in console, I can see the fields in the objects, but I cannot see any of the functions.
What is going on?
When you return something from an object used as a constructor, as the above code does, that value is the result of the new call. Note that neither returned object (this.response and this.optionGroup) has the functions you're interested in calling.
The simplest solution is to remove the returns.
Dunno if Matt's answer was clear, but:
> return this.optionGroup;
means the function returns the optionGroup object, not the new object referenced by this.
Constructors return this by default, so no return statement at all is equivalent to:
return this;
Same for the Response function.
Assuming of course that you are calling the functions with new.
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); });
});