Multiple calls to same Meteor method in for loop - angularjs

Use Meteor and AngularJS, I have the following setup:
ctrl.js
for(var i = 0; i < result.length; i++){
Meteor.call('serverMethod', arg1, arg2, function(err, res){
console.log(res);
});
}
methods.js
'serverMethod' (arg1, arg2) {
return HTTP.call("GET", "http://example.com/foo/var");
}
With the aim being that, for each element in result, it would call the Meteor method on the server, which would make a HTTP GET request, returning some data and then logging that data.
This all works, however it is doing it one at a time (make request, wait for result, make next request). I thought this would all run asynchronously?
What have I missed here/ what can I improve?

You need to use this.unblock(); inside your meteor method here is a page for more info.

Related

Postman - How do I loop a request in another request's test script?

I have a request that returns an array and I, thanks to StackOverflow, figured out how to make each object in the array its own environment variable. Now I want to make a request per variable in the same request as I instantiated the variable. Here is what I got:
var a = pm.response.json();
for (i = 0;i < a.sick_beats.length; i++){
pm.environment.unset("Beat_" + (i+1));
pm.environment.set("Beat_" + (i+1), a.sick_beats[i]);
pm.sendRequest("Publish Beat");
}
It sends the request "Publish Beat" but uses it as the URL instead of referencing the request.
I guess my question is how can I reference a request name instead of a URL, since the old way postman.setNextRequest("Request_Name"); doesn't work.
This pm.* function doesn't work in this way:
pm.sendRequest("Publish Beat")
Check out this blog from Postman explaining it more.
This is a basic extract from the snippets in the application. The first arg is the URL.
pm.sendRequest("https://postman-echo.com/get", function (err, response) {
console.log(response.json());
});
You can use pm.setNextRequest('request_name') to create a workflow but this will only work in the Collection Runner and not for single requests. You can add a collection of requests and chain these together using the {{Beat_1}} variable in the URL.
Alternatively, you could add something like this but it's very hacky and wouldn't ever send requests over and over again, like the collection runner would:
var some_value = pm.environment.get('Beat_whatever')
pm.sendRequest(`https://your-super-secret-site.com/${some_value}`, (err, response) => {
// This is just here so you can see the response
console.log(response.json())
})

Unit Test Multiple HTTP Requests

So in my factory I have a loop which requests HTTP calls and adds them to a promise array.
I then do a $q.all on the result to build a model.
When I come to test this however I can't get HTTP to make all the calls, it only makes the last one, I need it to make all the calls and build the model.
Below is very cut down code, ( I use 7 dates, but wanted to keep things short)
Factory Code
function getLatestData(){
var dateArray= ['2017-09-21','2017-09-22']
for (i = 0; i < 2; i++) {
var url = 'data-server/date/[i]'
promises.push(getData(url)); // getData is a simple $http function call.
}
return $q.all(promises).then(function(response){
buildModel(reponse);
});
}
So when I come to test this, I've got something like (I did try a loop but that failed).
httpBackend.expectGET('data-server/date/2017-09-21' ).respond(mockData[0]);
httpBackend.expectGET('data-server/date/2017-09-22' ).respond(mockData[1]);
rootScope.$apply();
modelFactory.getLatestData().then(function(response){
expect(response).toEqual(mockModelData);
})
So I console.log the get URL and I see all the URL requests are the same, they don't seem to be updating which results in this error
Error: Unexpected request: GET 'data-server/date/2017-09-22'
Expected GET 'data-server/date/2017-09-21'
because it's always the last httpBackend.expectGET that's taken.
What am I missing?
My problem was mocking.
I left this out of my example because I thought it wasn't relevant and added complication, but to build the dates I used the momentJS Library.
so
var url = 'data-server/date/[i]'
is
var url = 'data-server/date/'+factory.getMoment().add(i,'d').format('YYYY-MM-DD');
The factory.getMoment is just a wrapper for moment, the idea being I could over ride this in the unit tests to provide me with a 'given' date object.
funciton getMoment(){
return moment();
}
Anyway in my tests, I had this
var mockDate = moment('2017-09-21');
spyOn(factory, 'getMoment').and.returnValue(moment('2017-09-21'));
httpBackend.expectGET('data-server/date/'+mockDate.format('YYYY-MM-DD').respond(mockData[0]);
httpBackend.expectGET('data-server/date/'+mockDate.add(1,'d').format('YYYY-MM-DD').respond(mockData[1]);
Thinking that each time this would be called, it would give me back this mock, guess I was wrong about that.
What I needed to do, as pointed out by a colleague, was to use jasmine's clock mock.
beforeEach(function () {
jasmine.clock().install();
})
afterEach(function () {
jasmine.clock().uninstall();
})
Then in my test I set up the date time with
mockDate = moment('2017-09-21'); // always use moment as JS date if badly broken and just can't be trusted!
jasmine.clock().mockDate(mockDate.toDate());
httpBackend.expectGET('data-server/date/'+moment().add(0, 'days').format("YYYY-MM-DD").respond(mockData[0]);;
httpBackend.expectGET('data-server/date/'+moment().add(1, 'days').format("YYYY-MM-DD").respond(mockData[1]);;
(the above is in a loop)
I've removed my spy and now I have the dates and requests working as I expected.
Hope this helps someone else who finds themselves scratching their head for days trying to figure out why their tests are not working!

Not sending sms on loop with cordova plugin

I am trying to send sms on loop with Cordova plugin.
The issue that big part of SMS not sent.
Dose cordova have some limitation or should I do some ideal time?
this my code:
var contactsLen = $scope.contacts.length;
for (var i = 0; i < contactsLen; i++) {
if ($scope.contacts[i].hasOwnProperty('number')) {
$cordovaSms
.send($scope.contacts[i].number, text)
.then(function () {
if (i == contactsLen - 1) {
$scope.log += 'send All!'
}
}, function (error) {
The plugin code that sends the SMS is asynchronous, which means running it in a loop like that will not work the way you expect. If you want to fire multiple async events and wait for them all to finish, then you need to use something like q$ (https://docs.angularjs.org/api/ng/service/$q) to handle it. Make note of the all() method which lets you pass an array of promises.

Nodejs not sending response to Angular?

I have a doozy that I can't figure out whats going on.
In Mongo, I do a document.find(), which returns an array of object/s - All good.
I'm then trying to send on two objects back to the Angular Controller, the document object/s and the length of the array of objects.
Code:
function loadConnections(req, res) {
getConnections(req.user)
.then(function(results){
console.log('here');
console.log(results);
console.log(results.length);
var returnObject = {}
returnObject.count = results.length;
//returnObject.results = results[0]; // PROBLEM LINE
res.status(200).send(returnObject);
});
}
Problem I'm facing. In this scenario, it returns an array with 1 object. The array looks like:
[{id: XXX, test: YYY, test1: ZZZ}]
These have been what I've tried and tested:
returnObject.results = results[0].id; // works
returnObject.results = results[0].test; // works
returnObject.results = results[0].test1; //works
returnObject.results = results[0]; // doesn't work
returnObject.results = results; //doesn't work
But if I try to pass the entire object or the entire array, it hits an issue and doesn't send the response to the controller.
Any thoughts?
If you are using express, try to do a
res.send(200, returnObject);
or
res.json(200, returnObject);
that should do the trick!
Personally I would just calculate the length of the array after it arrives in my Angular client, rather than on the server. However, you should be able to accomplish what you're trying to do by doing this:
var returnObject = {
'count': results.length,
'results': results
};
res.json(returnObject);
Here's the doc: http://expressjs.com/en/api.html#res.json
Also just for general troubleshooting, the first thing you want to do is figure out where the inconsistency is starting. Does the data look right on the server before you send the response? Does the data look right on the client when your API handler receives the response? (I'm assuming $resource, or maybe you're using $http). So add a line like this just before you send the response from the server, and then add a similar line just after you receive the response in the client:
console.log(JSON.stringify(returnObject, null, 2));
Turns out it was my lodash library. I was using _.pluck and somewhere along the way, it's stopped working. Had to update it to _.map.

AngularJS app freezes during query

I am running an Angular app with a Parse backend. When I make a query, the app freezes, even when the DOM doesn't depend on the data being grabbing at the time. That is why this answer was not so helpful. Is there any way to have the rest of the app run along while some request is in progress?
Below is the code that freezes everything until the request resolves. The Parse Javascript SDK comes with promises, which is what 'QS.errorQuery.find()` returns.
function get() {
var queries = [
QS.errorQuery.find(),
QS.resLogQuery.find()
];
return $q.all(queries)
.then(function(res) {
return {
errors: res[0],
logs: res[1]
}; //end return
}); //end return
}; //end get
get().then(function(res) {
$scope.lineData = DP.bigLineParser(res.errors, res.logs);
});
The request is async so as the response is coming in, your UI wont freeze up. The long delay is probably happening when Parse gets its response from the server and parses it.

Resources