Pass query results object to separate function - javascript

This fiddle shows more or less what I am trying to do.
I am querying some results from a Parse.com database. The results are returned in the success callback.
Can anyone tell me the best way to work with them in the mainView() function? I would like to keep all queries separate from the logic of how they are displayed. I have tried quite a few different approaches, but haven't been able to get it working.

Simply store a reference to this outside the callback.
var userInterface = {
newQuery: function() {
var that=this; //store a reference to "this"
Query = Parse.Object.extend("Test");
query = new Parse.Query(Query);
query.descending("createdAt");
query.equalTo("column1", "a");
query.find({
success:function(results){
that.mainView(results); //that points to the userInterface object
},
error:function(error){
}
});
},
mainView: function(res){
console.log(res);
},
init: function() {
this.newQuery();
}
};
userInterface.init();
http://jsfiddle.net/4XsLq/8/

Related

Requesting Function Response in another function

I have those two functions where i call "http" from "Count" the "http" return promise. I want to use the return value of "http" in "Count". What I receive now is Undefined !!!
What I'm missing ?
Count Function :
Parse.Cloud.define('count', function(request, response) {
var query = new Parse.Query('MyS');
query.equalTo("Notify", true);
query.notEqualTo ("MainEventCode", '5');
query.find({
success: function(results) {
Parse.Cloud.run('http', {params : results}).then(
function(httpResponse) {
console.log('httpResponse is : ' + httpResponse.length);
response.success('Done !');
}, function(error) {
console.error(error);
});
},
error: function(error) {
response.error(error);
}
});
});
http Function :
Parse.Cloud.define('http', function(request, response) {
var query = new Parse.Query(Parse.Installation);
.
.
.
}
Relying on calling your own functions through an external interface is not a very good practice.
Now that you've realized you're going to need the same code for a different purpose, you should take the time to refactor your code such that you don't need to call the 'http' handler through Parse.Cloud.run():
function doHttp(params) {
// original implementation here
}
Parse.Cloud.define('http', function(request, response) {
doHttp(request.params)
.then(response.success)
.fail(response.error);
}
Parse.Cloud.define('count', function(request, response)) {
var query = new Parse.Query('MyS');
query.equalTo("Notify", true);
query.notEqualTo ("MainEventCode", '5');
query.find()
.then(doHttp) // doHttp will receive the results from `query` as its parameter
.then(function(httpResponses) {
// httpResponses is an array-like object as per the other question:
httpResponses = Array.prototype.slice.call(httpResponses);
httpResponses.forEach(function (response) {
console.log('httpResponse is : ' + response.length);
});
}).fail(response.error);
}
I've taken a look at the other question and as far as the implementation of count goes, I believe you're missing the point that 'http' is returning arguments, which is only an Array-like object.
This should be okay if Parse.Cloud.run runs your function on another virtual machine, but this kind of weird behaviour is another symptom of not refactoring and reusing your code through an external call (an HTTP request inside their infrastructure with JSON passing! It might greatly reduce performance and count against your requests/second quota). If Parse instead does some magic to call your function directly as if it was defined on the same environment, you're going to have problems with it not being an actual Array.
You should modify that function to return a proper array if possible. Parse CloudCode has a version of the Underscore library:
// on http
var _ = require('underscore');
Parse.Promise.when(promises).then(function() {
var results = _.toArray(arguments) // equivalent to Array.prototype.slice above
response.success(results);
}
I think what you're asking is how to use an externally callable cloud function as a step in a bigger cloud procedure. Here's how to do it: (#paolobueno has it essentially correct, with only a couple mistakes in the details).
First, let's convert that 'http' cloud function to a regular JS function. All we need to do is factor out the request and response objects. (#paolobueno has a very good idea to use underscorejs, but I won't here because its another new thing to learn).
// for each object passed in objects, make an http request
// return a promise to complete all of these requests
function makeRequestsWithObjects(objects) {
// underscorejs map() function would make this an almost one-liner
var promises = [];
for (var i = 0; i < objects.length; i++) {
var object = objects[i];
promises.push(makeRequestWithObject(object));
}
return Parse.Promise.when(promises);
};
// return a promise to do just one http request
function makeRequestWithObject(object) {
var url = 'http://185.xxxxxxx'+ object +'&languagePath=en';
return Parse.Cloud.httpRequest({ url:url });
}
It looks like you want the updated cloud function -- rather than use params from the client -- to first make a query and use the results of that query as parameters to the http calling function. Here's how to do that. (Again, using #paolobueno's EXCELLENT practice of factoring into promise-returning functions...)
// return a promise to find MyS instances
function findMyS() {
var query = new Parse.Query('MyS');
query.equalTo("Notify", true);
query.notEqualTo ("MainEventCode", '5');
return query.find();
}
Now we have everything needed to make a clear, simple public function...
Parse.Cloud.define('count', function(request, response) {
findMyS().then(function(objects) {
return makeRequestsWithObjects(objects);
}).then(function(result) {
response.success(result);
} , function(error) {
response.error(error);
});
});

Javascript WebSQL use one transaction object all the time

Hello I have factory which gives functions to work with database, it looks like this:
.factory('DBwork', function () {
var db = openDatabase("...");
db.transaction(function(tx){
tx.executeSql("CREATE TABLE...");
});
var factoryfunctions = {
insert: function() {
db.transaction(function(tx){
tx.executeSql("INSERT INTO...");});
},
select: function() {
db.transaction(function(tx){
tx.executeSql("SELECT FROM...");});
}
};
return factoryfunctions;
});
I need to use one transaction object all the time, or not use transactions at all, is that possible?
Simply, to make it like this.
var db = openDatabase("...");
tx = db.transaction();
var factoryfunctions = {
insert: function() {
tx.executeSql("INSERT INTO...");
},
select: function() {
tx.executeSql("SELECT FROM...");
}
};
return factoryfunctions;
Im new to javascript so thanks for any help
It doesn't make sense to cache transaction object for later use. It is unusable after transaction callback has completed. In specification's terms it's marked stale, so that any other call to its executeSql() throws an exception.
There are only three methods available on the database object, transaction(), readTransaction() and changeVersion(). There isn't a way to avoid transaction objects.
What you can do however, is call executeSql() multiple times in one transaction callback.
See this example, http://html5demos.com/database-rollback.

How to fetch an object in Parse Cloud Code

I am working on a parse cloud code function which performs a query and filters the results afterwards. These are my first lines of code written in JavaScript, so I have no clue how to solve the following problem.
The problem is, that my filter predicate needs some elements stored in the someArray variable. All elements of someArray aren't fetched yet. But fetching an an Parse.Object is a asynchronous call, so I have no chance to return trueor false expected by filter().
How can I solve this problem?
Or I am misinterpreting the fact, that when I don't fetch the arrayElement
console.log("arrayElement with name: ".concat(typeof(arrayElement), arrayElement.get("name")));
prints
arrayElement with name:objectundefiend
although I know that Object represented by arrayElment has a name-column which is always defined?
//The cloud code
Parse.Cloud.define("search", function(request, response) {
var query = new Parse.Query("Location");
query.withinKilometers("gps", request.params.searchLocation, request.params.searchRadius / 1000);
query.find({
success: function(results) {
// results is an array of Parse.Object.
var locations = results.filter(function(location) {
console.log("Location with name: ".concat(location.get("name")));
var someArray = location.get("someArray");
if (someArray instanceof Array) {
console.log("The array of this location has ".concat(someArray.length, " elements."));
someArray.forEach(function(arrayElement) {
arrayElement.fetch().then(
function(fetchedArrayElement) {
// the object was fetched successfully.
console.log("arrayElement with name: ".concat(typeof(fetchedArrayElement), fetchedArrayElement.get("name")));
if (menuItem) {};
return true;
},
function(error) {
// the fetch failed.
console.log("fetch failed");
});
});
}
});
response.success(locations);
},
error: function(error) {
// error is an instance of Parse.Error.
response.error(error);
}
});
});
some useful links:
Parse JavaScript SDK API
Parse Cloud Code Guide
If I'm reading this right, you've got an array column of Parse Objects. You should use the include method on your query so that the objects are fetched in the initial query.
query.include('someArray');
I don't think you'll want to use a filter, and should take a look at the Promises documentation here: https://parse.com/docs/js_guide#promises
You're right that since it's asynchronous, you need to wait for everything to be done before calling response.success which doesn't currently happen in the code. Promises and defining your own async functions that use Promises is a great way of chaining functionality and waiting for groups of functions to complete before going forward.
If all you wanted to do what include that column, the whole thing should just be:
Parse.Cloud.define("search", function(request, response) {
var query = new Parse.Query("Location");
query.include('someArray');
query.withinKilometers("gps", request.params.searchLocation, request.params.searchRadius / 1000);
query.find().then(function(results) {
response.success(locations);
}, function(error) {
response.error(error);
});
});

How to use angularFireCollection initial load callback?

I've been trying to handle properly in my angular service an explicit synchronization with Firebase. I use angularFireCollection with initial load callback function (I need to preload additional data basing on the data returned by the first query). However, I don't know how should I access the fetched data in the callback function:
getGroupIds: function() {
var deferred = $q.defer();
var ref = new Firebase('https://<XXX>.firebaseio.com/groups');
angularFireCollection(ref, function(groups) {
console.log(groups);
deferred.resolve(groups);
});
return deferred.promise;
}
In the above example, how can I access actual data from groups object?d
Thanks in advance for any tips.
A Firebase snapshot is provided as an argument to the callback function, and you can extract the value from it as follows:
angularFireCollection(ref, function(snapshot) {
console.log(snapshot.name() + " has value " + snapshot.val());
});
usually, I'm setting the collection to scope, but either of these seem to work.
var groups = angularFireCollection(ref, function() {
console.log(groups);
});
or in a controller
$scope.groups = angularFireCollection(ref, function() {
console.log($scope.groups );
});

Returning a value from 'success' block in JS (Azure Mobile Service)

I have a rather simple getUser method that I'm having some trouble with. I am not deeply familiar with scopes and such in JS so this is giving me a head ache. Basically I want to fetch an object from the database and return it to the calling method:
function getUser(uid)
{
var result = null;
var userTable = tables.getTable('Users');
userTable.where({
userId: uid
}).read({
success: function (results) {
if (results.length > 0) {
result = results[0];
console.log('userid'+result.id);
}
}
});
console.log('userid-'+result.id); // undefined!!
return result;
}
Also, returning from inside the success doesn't return from getUser, but just the function defined inside. I tried "result = function(results)" as well but it stores the defined function and not the return value.
How am I supposed to do this?
I found a solution to this elsewhere. In practice (to the best of my understanding), it is not possible to do this within a JavaScript with asynchronous functions. What you need to do is create a recursion instead from inside the success handler.
Because the call to the database is asynchronous, your last two lines are executed (and hence result is undefined) before the call the database actually finishes. So you need to handle everything inside your success callback. Or, if your getUser() func is a helper, you could structure your code (without recursion) like this with a callback:
function insertOrWhateverCallingMethod()
{
var uid = 'blah';
getUser(uid,function(user) {
// Do something with the user object
});
}
function getUser(uid,callback)
{
var result = null;
var userTable = tables.getTable('Users');
userTable.where({
userId: uid
}).read({
success: function (results) {
if (results.length > 0) {
result = results[0];
console.log('userid'+result.id);
callback(result);
}
}
});
callback(null);
}
The code above assumes you're in a table script, where the tables object is available - if it's not you can pass it as a parameter to getUser().

Categories

Resources