How can I make my code run sequentially? For example,
If I have a for loop which gets some data from a service, I want the n+1 iteration to run
You could wrap each iteration in a Promise and await it:
async function someMethod() {
for (var i = 0; i < 5; i++) {
await new Promise(resolve => {
setTimeout(()=> {
console.log('This is iteration ' + i);
resolve();
}, 500);
});
}
console.log ('print me only after all iterations');
}
someMethod();
You can do it with Promise.
someMethod() : Promise<any> {
return new Promise((resolve) => {
for ( var i = 0; i < someLength; i++) {
// get some data
this.dataService.get(i).subscribe(data => {
// do something with the data
});
if(i==someLength-1){resolve();}
}
}).then(()=>{
//
console.log ('print me only after all iterations');
// ....
// some more lines of code
})
}
Are you looking for something like this? (plunker)
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`;
this.someMethod();
}
doTimeout(currentIndex:int){
return new Promise(resolve => {
setTimeout(()=> {
console.log("This is iteration " + currentIndex);
resolve();
},500);
});
}
async someMethod() {
for(let i=0;i<5;i++){
await this.doTimeout(i);
}
// I want to execute this line of code only after the
// for loop has completed all iterations.
console.log ('print me only after all iterations');
// ....
// some more lines of code
}
}
Sources: What is the JavaScipt Version of sleep? and Combination of async function + await + setTimeout
I suggest adapting it to use the zip "combining operator" from rxjs:
http://reactivex.io/documentation/operators/zip.html
EDIT: here is an example: https://www.learnrxjs.io/operators/combination/zip.html
Although in your case you would have to pass it as an array probably ( zipArray).
As Javascript is a single thread language, it is hard to do what exactly you want to achieve unless you use Promise or other callback architecture.
There are many ways to achieve it through PROMISEs. Here, I'll show you how can you achieve the same using advance JavaScript concept called Async & Await in Angular framework.
Please note there are many ways with Promise but my intention is to introduce you to new async & await concept where you don't need to chain the callback for success and reject methods.
DEMO : https://plnkr.co/edit/16k66yRjXLPwTM50kYNS
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`;
this.someMethod();
}
const someMethod_Promise = () => {
return new Promise((resolve,reject)=>{
for ( var i = 0; i < 5; i++) {
console.log('printing value of i ' + i);
if(i==4) // real condition
resolve(true);
}
})
}
const someMethod = async()=>{
let result= await this.someMethod_Promise();
if(result){
console.log ('print me only after all iterations');
}
}
}
Promise based solution:
Promise.all() takes an array of promises and fires them all at the same time. Then once all of the promises resolve it will run the callback.
let dataService = {
get: function(i) {
return new Promise((resolve, reject) => {
setTimeout(resolve, 100, i);
});
}
}
let promises = [];
for (var i = 0; i < 3; i++) {
// get some data
promises.push(dataService.get(i));
}
Promise.all(promises).then(values => {
console.log ('print me only after all iterations');
console.log(values);
});
Working sample: http://jsbin.com/ruqiwoxono/edit?js,console
Promise.all docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Rxjs based solution:
forkJoin basically does the same thing as Promise.all() but for observables
let dataService = {
get: function(i) {
return Rx.Observable.of(i);
}
}
let observables = [];
for (var i = 0; i < 3; i++) {
// get some data
observables.push(dataService.get(i));
}
const example = Rx.Observable.forkJoin(observables);
const subscribe = example.subscribe(values => {
console.log ('print me only after all iterations');
console.log(values);
});
Working sample: http://jsbin.com/jolotuyoxa/edit?js,console
Rxjs forkjoin docs: https://www.learnrxjs.io/operators/combination/forkjoin.html