Getting urls one after another - angularjs

I am trying to call urls one AFTER another, not all at the same time, but no matter what I seem to try, they seem to all happen at the same time. This is what I have now...
$http.get('/some/url/foo1')
.then($http.get('/some/url/foo2'))
.then($http.get('/some/url/foo3'))
.then($http.get('/some/url/foo4'))
.then($http.get('/some/url/foo5'))
.then($http.get('/some/url/foo6'))
.then($http.get('/some/url/foo7'))
.then($http.get('/some/url/foo8'))
.then($http.get('/some/url/foo9'))
.then($http.get('/some/url/foo10'))
.then($http.get('/some/url/foo11'))
.then($http.get('/some/url/foo12'))
.then($http.get('/some/url/foo13'))
.then($http.get('/some/url/foo14'));
These can't happen at the same time, when one completes, I want the next one to start.
EDIT: I've also tried putting the get in a function like this, but they still all get called at the same time
$http.get('/some/url/foo1')
.then(rebuildModel('foo2'))
.then(rebuildModel('foo3'))
.then(rebuildModel('foo4'))
.then(rebuildModel('foo5'))
.then(rebuildModel('foo6'))
.then(rebuildModel('foo7'))
.then(rebuildModel('foo8'))
.then(rebuildModel('foo9'))
.then(rebuildModel('foo10'))
.then(rebuildModel('foo11'))
.then(rebuildModel('foo12'))
.then(rebuildModel('foo13'))
.then(rebuildModel('foo14'));
function rebuildModel(modelName) {
return $http.get('/some/url/' + modelName);
}
Edit2: This worked...I see what I did wrong
function rebuildModel(modelName) {
return function () {
return $http.get('/some/url/' + modelName);
}
}

The then method expects a success callback function as its first parameter:
$http.get('url').then(successCallback);
The successCallback must be a function definition, such as:
$http.get('url').then(function() { ... });
If you provide $http.get() as an argument:
$http.get('url').then($http.get('url'));
You are calling a function, and then passing the return value (which is a promise object) to the then method as the successCallback.
The situation is analogous to the following more obvious scenario:
a. alert
b. alert()
The first is a function definition, the second is calling the function.
I agree with Chandermani's answer, and it should be correct. If it is not working, perhaps check for errors:
$http.get('/some/url/foo1')
.then(function() { return $http.get('/some/url/foo2'); })
.then(function() { return $http.get('/some/url/foo3');},
function() { alert('something went wrong');});

The chaining that you have done is incorrect. It should be something like this:
$http.get('/some/url/foo1')
.then(function() { return $http.get('/some/url/foo2'); })
.then(function() { return $http.get('/some/url/foo3');})
Remember the then function too returns a promise, that is resolved by the return value of its, success and error callbacks.

Related

Redux - Async-Await response undefined but 'works' [duplicate]

I'm new to JavaScript, and I try to play around with it to understand all in-and-outs. I write
function greet() {
console.log("Hi");
};
console.log(greet());
And the result of it in the console is
> Hi app.js:2
> undefined app.js:4
I assume this is because greet() inside console.log first calls the function, which prints out "Hi". We get first line of log. But where did the second line come from?
Then I thought because Hi is overall result of greet(), then console.log basically calls variable Hi, but in this case the result would be is not defined, not undefined
In JavaScript, if nothing is returned from the function with the keyword return then undefined is returned by default.
var data = greet();
console.log(data);// undefined, since your function does not return.
Is equivalent to:
console.log(greet());
The second output is the returned result from the function. Since you are not returning anything from the function hence prints undefined.
To print 'Hi' in the second console you have to return that from the function.
function greet() {
console.log("Hi");
return 'Hi';
};
console.log(greet());
You should use a return keyword like this:
function greet() {
console.log("HI");
return "HI";
};
console.log(greet());
Or you can store it in a variable and return the variable:
function greet() {
const hello = ("HI");
return hello;
};
cosnole.log(greet());
,Because if you don't use return keyword and log the function to the console then it returns undefined.

AngularJS $promise executes only once

Is any way that $promise can execute multiple times or any alternate in angular.
Refer below code.
Sample Code:-
promise.then(function(greeting) {
alert('Success: ' + greeting);
}
...
if () {
resolve('Hello, ' + name + '!');
} else {
reject('Greeting ' + name + ' is not allowed.');
}
Yup, it will only execute only once, might be in angularJS you will not get alternative. You can try jQuery or some thing else. :)
You could probably use the notify callback
notify(value) - provides updates on the status of the promise's execution. This may be called multiple times before the promise is either resolved or rejected.
The following (untested) code should notify ten times with the numbers 1-10 and then resolve with the message "Done counting".
function countToTen() {
return $q(function(resolve, reject, notify) {
for (var counter=1; counter <= 10; counter++) {
setTimeout(function() {
notify(counter);
}, 1000 * counter);
}
setTimeout(function() { resolve("Done counting"); }, 10001);
});
}
Edit : as ARedHerring notices, notify isn't part of any promise standard and should be considered bad practice.
The contract of a promise is that it will only ever resolve once, and honestly I can't really imagine any scenarios where it makes sense for it to execute more than once. After a promise has resolved, any subsequent calls to then will be invoked upon the next event loop tick as the value of the promise has already been resolved and will be cached.
This seems like an XY problem. Could you explain what you are trying to do in more detail?
You can go through this forum where Thomas has told how you can resolving a promise multiple times.
$rootScope.$apply( function() {
deferred.resolve( incremented );
});

Do the return codes in Backbone.Event matter?

Do the return codes for the callback given to Backbone.Event matter at all? Is there a convention for them?
obj.on( "event_name", function () { return true; } )
vs
obj.on( "event_name", function () { return false; } )
The only way you can really be sure is to check the backbone source. Here's the function that internally calls events:
https://github.com/jashkenas/backbone/blob/master/backbone.js#L303
It's a little hard to read because it's been heavily optimized. The actual call occurs on one of the five instances of (ev = events[i]).callback.call. In any of those cases, the return value is not used.
So it should be pretty clear that Backbone just discards the return value of the callbacks.

Re-use array collection on multiple pages

I currently have 2 pages, page1.php and page2.php, each of the pages uses a controller that completes its own functions etc.
However there are tabs within the pages that are exactly the same that gets a promise from a factory within the module. The lists are exactly the same except for querying on different IDs. For example both controllers have this:
pageListFactory.getData().then(function (result) {
$scope.BasicItems = result; $scope.basicItemsList = [];
angular.forEach($scope.BasicItems, function (BasicItem) {
angular.forEach(BasicItem['SomeInnerArray'], function (BasicSomeInnerItem) {
if (BasicSomeInnerItem == VARIABLE_THAT_CHANGES) {
$scope.basicItemsList.push({
ID: BasicItem.ID, Title: BasicItem.Title
});
}
});
});
});
So this code is used, and the VARIABLE_THAT_CHANGES is just what changes each time. However as I said it is used on multiple pages, is there a way to create just one function call and then each page just can call a specific bit and send the variable with it?
I tried using $rootScope but of course this just clogs and slows, and I'm not exactly happy on constantly using $rootScope to pass the $scope.basicItemsList around as the list could get quite big.
So is there any way to reuse this code without just copying and pasting it into each controller?
Sure you can re-use it...
Convert the factory to a service, its basically a name change, create a local variable to store the data, update the data on first call, and then grab the data if it exists on the second call.
.service('myService', ... stuff ... { // I suggest using a service, as I don't know if a factory would act as a singleton
var myData = null;
return {
getData: function(){
if(myData != null)
return myData; // returns data
else {
return $http()... // ajax call returns promise
}
},
setData: function(dataToSet){
myData = dataToSet;
}
}
Then your controllers:
//controller 1
var promiseOrData = pageListFactory.getData();
if(promiseOrData instanceOf Array){ // or whatever data you expect
$scope.BasicItems = promiseOrData;
....
}
else { // should be a promise
promiseOrData.then(function (result) {
pageListFactory.setData(result); // set the data once you get it.
$scope.BasicItems = result; $scope.basicItemsList = [];
....
}
}
In controller 2 you only need to get the data as the returned data will be an array, not a promise
On top of all this, write a directive which will process the data when you pass it along, then you can pass the variableThatChanges and have the directive take care of it.
Use services and write the function in that service and pass the variable VARIABLE_THAT_CHANGES into it. By this you can reuse the code.

Angular promises run conditionally

I'd like to perform an asynch function conditionally, but I think I'm missing the correct syntax to say what I want.
this.doUpToThreeThings = function(skipTheMiddleStep) {
return doFirstThing().then(function (result) {
if (skipTheMiddleStep) {
return doThirdThing();
} else {
return doSecondThing();
}
}).then(function (result) {
if (skipTheMiddleStep) {
return "ok"; // return what?
} else {
return doThirdThing();
}
});
}
By the time we get to the second then, I don't know if the first block did the middle step, so I'm forced into repeating the condition. And the second block reads weird: it should say, if skip the middle step, then do the third thing, but since it we know that the previous block must have done the third thing, it just returns. So I have to repeat the condition and write pretty wrong-looking code in the second then.
I realize I can write a function called doSecondAndThirdThings, and just call that from the condition in the first block, but that's not really DRY, it's just hiding the non-DRYness. (or maybe I'm wrong about that?)
Also, I'm still a little confused about returning a completed promise on that "ok" branch. Is that right how it is, or should I say something like resolve? -- Thanks
The deferred in thefourtheye's answer is pointless and is considered an anti pattern with promises.
Here is how I would do it:
this.doUpToThreeThings = function(skipTheMiddleStep) {
return doFirstThing().then(function (result) {
return (skipTheMiddleStep) ? doThirdThing() : doSecondThing().then(doThirdThing);
});
}

Resources