$promise stays promised on 'then' function - javascript

I'm using angular's $resource to perform a GET operation. This is how I do it:
var query = {customerid: $stateParams.customerid}
$resource('api/reports/running_count').get(query).$promise.then(function(value) {
$scope.runningInstance = value;
});
I also tried it like that:
$resource('api/reports/running_count').get(query, function(value) {
$scope.runningInstance = value;
});
The request returns a number. I checked the response with chrome's developer-tools. The request is indeed sent as follows:
<base-url>/api/reports/running_count?customerid=<id>
The response returns a number, again as expected.
But when I put a breakpoint in the callback function, the value is again a promise and not a number. Not sure what I'm doing wrong.

The $resource service doesn't work when the response is a primative. It uses angular.copy to copy the data to the $resource object and angular.copy doesn't copy a primative to an object. It can only make deep copies of properties of other objects.
From the Docs:1
angular.copy
Creates a deep copy of source, which should be an object or an array.
If a destination is provided, all of its elements (for arrays) or properties (for objects) are deleted and then all elements/properties from the source are copied to it.
If source is not an object or array (inc. null and undefined), source is returned.
In your case the source was not an object and you were getting just the $promise property which the $resource service attaches to the resource object.

From angular example https://docs.angularjs.org/api/ngResource/service/$resource:
var User = $resource('/user/:userId', {userId:'#id'});
User.get({userId:123}, function(user, getResponseHeaders){
user.abc = true;
user.$save(function(user, putResponseHeaders) {
//user => saved user object
//putResponseHeaders => $http header getter
});
});
Just put you values there.

As far I know if you want to get data using query value then server get query value as a string. it is useful when you will send query from search box . for example want to search product by name or something else then you can use like.
in service:
var query = {productname: '123'}
getProducts: function(query) {
var getProducts = $resource('/api/products', {}, {
'get': {method: 'GET', isArray: true}
});
return getProducts.get(query);
}
and server side will receive as req.query.productname so productname as a string so you need to convert it to number if needed as number.
but if you want to find produt by id you should send id as a parameter not query for exactly matching that also may send as string.
for example in service:
getProductById: function(id) {
var getProductById = $resource('/api/products/:id', {id: '#id'}, {
'get': {method: 'GET'}
});
return getProductById.get({id: id});
}
so server side will receive as req.params.id

Related

Sending an array with axios.get as params is undefined

I am making a get request with additional params options, since I am using that request on a filter, so the params are filters for what to get back:
const res = await axios.get("http://localhots:3000/getsomedata", {
params: {
firstFilter: someObject,
secondFilter: [someOtherObject, someOtherObject]
}
});
The request goes through just fine, on the other end, when I console.log(req.query); I see the following:
{
firstFilter: 'someObject',
'secondFilter[]': ['{someOtherObject}', '{someOtherObject}'],
}
If I do req.query.firstFilter that works just fine, but req.query.secondFilter does not work and in order for me to get the data, I have to do it with req.query["secondFilter[]"], is there a way to avoid this and be able to get my array of data with req.query.secondFilter?
My workaround for now is to do:
const filter = {
firstFilter: req.query.firstFilter,
secondFilter: req.query["secondFilter[]"]
}
And it works of course, but I don't like it, I am for sure missing something.
Some tools for parsing query strings expect arrays of data to be encoded as array_name=1&array_name=2.
This could be a problem if you have one or more items because it might be an array or might be a string.
To avoid that problem PHP required arrays of data to be encoded as array_name[]=1&array_name[]=2 and would discard all but the last item if you left the [] out (so you'd always get a string).
A lot of client libraries that generated data for submission over HTTP decided to do so in a way that was compatible with PHP (largely because PHP was and is very common).
So you need to either:
Change the backend to be able to parse PHP style
Change your call to axios so it doesn't generate PHP style
Backend
The specifics depend what backend you are using, but it looks like you might be using Express.js.
See the settings.
You can turn on Extended (PHP-style) query parsing by setting it to "extended" (although that is the default)
const app = express()
app.set("query parser", "extended");
Frontend
The axios documentation says:
// `paramsSerializer` is an optional function in charge of serializing `params`
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
So you can override that
const res = await axios.get("http://localhots:3000/getsomedata", {
params: {
firstFilter: someObject,
secondFilter: [someOtherObject, someOtherObject]
},
paramsSerializer: (params) => Qs.stringify(params, {arrayFormat: 'repeat'})
});
My example requires the qs module
This has to do with params not being serialized correctly for HTTP GET method. Remember that GET has no "body" params similar to POST, it is a text URL.
For more information I refer to this answer, which provides more detailed info with code snippets.

Parse - limit result of a Query in Cloud Code

Hello is this code in the comment possible with Parse Cloud Code?
Parse.Cloud.beforeFind('Note', function(req) {
var query = req.query;
var user = req.user;
// if a given 'Note' visibility is set to 'Unlisted'
// return only the Notes with 'user' field that the calling _User
});
The documentation only shows how to filter fields that are returned but not exactly remove items from the query result in the Cloud Code.
This can be done through ACL, I know, but the caveat is that if the request is a retrieve function and not query the Note should still return.
Assuming you've saved the user as an object relationship (not a string id). Just add the qualification you need, such as:
query.equalTo("your_user_pointer_col_on_Note", user)

Azure documentdb stored procedure returning partial result

Currently I have got given stored procedure
function getData() {
var context = getContext();
var collection = context.getCollection();
var output = collection.map(function (doc) {
return {
id: doc.id,
name: doc.name,
status: doc.status,
description: doc.description,
owner: doc.owner
}
})
return JSON.stringify(output)
}
Issue here is that it only returs 7 documents (matching what you get when you not get 'load' action on azure panel) and is skipping rest of the collection.
I believe that it can be fixed with using SQL query syntaxt but I would like to know how can I query all documents in the collection without using it.
Try adding a FeedCallback like shown here and make the signature of the callback be function(error, resources, options). Look for errors. Also inspect the options parameter for a continuation. If that fails to give you enough information to fix the problem, then you might want to consider a more traditional query and transformation approach not using collection.map().

opensocial newFetchPeopleRequest ignores parameters

I'm trying to get person info woth specifies fields:
var params = {};
params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = [
opensocial.Person.Field.NICKNAME,
opensocial.Person.Field.PROFILE_URL,
opensocial.Person.Field.GENDER,
opensocial.Person.Field.THUMBNAIL_URL,
opensocial.Person.Field.ADDRESSES,
opensocial.Person.Field.DATE_OF_BIRTH
];
params[opensocial.IdSpec.Field.USER_ID] = ids;
var idSpec = opensocial.newIdSpec(params);
var req = opensocial.newDataRequest();
req.add(req.newFetchPeopleRequest(idSpec), "profiles");
But on responce, whatever person fields I'm setting up, I always get same set of fields in return:
displayName, id, isOwner, isViewer, nickname, thumbnailUrl
how to get requested fields?
UPD:
If this is important, social network I'm working with is yahoo mobage.
You are populating the params object but you are not actually using it in the request. You are merely using it in the opensocial.newIdSpec() call which gives you an IdSpec object. However, if you look at the documentation of the IdSpec object - this one has only user-related fields, additional data is ignored. You should actually pass in params in your newFetchPeopleRequest() call:
req.add(req.newFetchPeopleRequest(idSpec, params), "profiles");
For reference: opensocial.DataRequest.newFetchPeopleRequest method.

Multiple Backbone.js collection options?

Intro:
Building in node.js and express on the backend, I am sending a res.json(details) to the localhost:3000/me route containing the users session information.
So that on the client side I can work with that specific user, for example on the client side initialization I write some code like this.
var me = new MeModel();
me.fetch({
success: function(response) {
App.data.me = me;
var messages = new MessagesCollection([], { id: response.get('user_id') });
messages.fetch({
success: function() {
App.data.messages = messages;
App.core.vent.trigger('app:start');
}
});
}
});
You see I fetch the me model and use that to filter the messages in the MessagesCollection.
Question:
In my MessagesCollection I pass options like this.
module.exports = MessagesCollection = Backbone.Collection.extend({
initialize: function(models, options) {
this.id = options.id;
},
url: function() {
return '/api/messages/' + this.id;
},
model: MessageModel,
//url: '/api/messages'
});
This is great for getting the desired models when using var messages = new MessagesCollection([], { id: response.get('user_id') });
My question is when somewhere else I run window.App.data.messages.create(Message); this wants to POST to /api/messages/:id when I want to POST to the regular collection?
Theory:
So obviously I would say the best thing is to rethink how I filter the models in the fetch method.
So basically to simplify this question I need to filter the collection upon .fetch() GET... and set no filters upon .create() POST
BTW I am using marionette, maybe that can help with something?
model.url() Returns the relative URL where the model's resource
would be located on the server. If your models are located somewhere
else, override this method with the correct logic. Generates URLs of
the form: "[collection.url]/[id]" by default, but you may override by
specifying an explicit urlRoot if the model's collection shouldn't be
taken into account.
Delegates to Collection#url to generate the URL, so make sure that you
have it defined, or a urlRoot property, if all models of this class
share a common root URL. A model with an id of 101, stored in a
Backbone.Collection with a url of "/documents/7/notes", would have
this URL: "/documents/7/notes/101"
http://backbonejs.org/#Model-url
So you can define method url at MeModel and generate url there ( if there are no other users - you can just return string "/me" or generate in based on model properties ( for example switch if model has id )

Categories