How to handle data comes late from service?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







2















In my angular application, i am in the need to store the data to an array which will be empty at initial stage.



Example:



someFunction() {

let array = ;

console.log("step 1");

this.service.getRest(url).subscribe(result => {

result.data.forEach(element => {

console.log("step 2");

array.push(element); // Pushing all the objects comes from res.data

});

console.log("step 3");

});

console.log("step 4");

}


Here i have listed down the console.log() with step order.



In which the order while calling the function was,



Step 1
Step 4
Step 2
Step 3



Here after step 1, the step 4 calls and later the step 2.. So if i console.log(array) in place of step 4, it gives again empty array..



But in place of step 2 and 3 it gives value.. Coming out of the service the value is empty.



And hence always i am getting empty value in the array.



Kindly help me to store the data to the variable even though there is a time duration of service call and response coming back.



Tried by modifying code for a long time but couldn't get it worked..



Edit:



I have given below the real time application i am currently working with stackblitz link https://stackblitz.com/edit/angular-x4a5b6-ng8m4z



Here in this demo see the file https://stackblitz.com/edit/angular-x4a5b6-ng8m4z?file=src%2Fapp%2Fquestion.service.ts



Where i am using the service call.. If i put async getQuestions() {}, it is giving error of questions.forEach of undefined



In service.ts



    jsonData: any = [
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_name",
"label": "Project Name",
"type": "text",
"value": "",
"required": false,
"minlength": 3,
"maxlength": 20,
"order": 1
},
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_desc",
"label": "Project Description",
"type": "text",
"value": "",
"required": true,
"order": 2
},
{
"elementType": "dropdown",
"key": 'project',
"label": 'Project Rating',
"options": ,
"order": 3
}
];

getQuestions() {

let questions: any = ;

//In the above JSON having empty values in "options": ,

this.jsonData.forEach(element => {
if (element.elementType === 'textbox') {
questions.push(new TextboxQuestion(element));
} else if (element.elementType === 'dropdown') {

//Need to push the data that comes from service result (res.data) to the options

questions.push(new DropdownQuestion(element));

console.log("step 1");

//The service which i call in real time..

// return this.http.get(element.optionsUrl).subscribe(res => {

//res.data has the following array, Using foreach pushing to elements.options.

// [
// { "key": 'average', "value": 'Average' },
// { "key": 'good', "value": 'Good' },
// { "key": 'great', "value": 'Great' }
// ],

// res.data.forEach(result => {
console.log("step 2");
// element.options.push(result);
// });
// console.log(element.options) give values as the above [
// { "key": 'average'...
console.log("step 3");
// console.log(element.options) give values as the above [
// { "key": 'average'...
// });
console.log("step 4");
//But here console.log(element.options) gives empty
}
});

return questions.sort((a, b) => a.order - b.order);
}









share|improve this question

























  • Not sure to understand the problem because it looks like you already have the solution: the service call is asynchronous so you'll get results in its callback (step 2 and 3). Here you can successfully fill array, so whatever you need to do with array, initiate it in the service callback.

    – Zim
    Nov 16 '18 at 13:34











  • I think this is basically just another duplicate of the old classic, stackoverflow.com/questions/14220321/…

    – misorude
    Nov 16 '18 at 13:34











  • @Zim, But if i console.log(array) in the place of step 4, then its giving empty array but in place of step 2 and 3, it giving value..

    – Maniraj from Karur
    Nov 16 '18 at 13:37











  • @undefined: yes, because at the time you reach step 4, the asynchronous call has not been finished yet!

    – Zim
    Nov 16 '18 at 13:44











  • put your result inside setTimeout

    – Chellappan
    Nov 16 '18 at 15:16


















2















In my angular application, i am in the need to store the data to an array which will be empty at initial stage.



Example:



someFunction() {

let array = ;

console.log("step 1");

this.service.getRest(url).subscribe(result => {

result.data.forEach(element => {

console.log("step 2");

array.push(element); // Pushing all the objects comes from res.data

});

console.log("step 3");

});

console.log("step 4");

}


Here i have listed down the console.log() with step order.



In which the order while calling the function was,



Step 1
Step 4
Step 2
Step 3



Here after step 1, the step 4 calls and later the step 2.. So if i console.log(array) in place of step 4, it gives again empty array..



But in place of step 2 and 3 it gives value.. Coming out of the service the value is empty.



And hence always i am getting empty value in the array.



Kindly help me to store the data to the variable even though there is a time duration of service call and response coming back.



Tried by modifying code for a long time but couldn't get it worked..



Edit:



I have given below the real time application i am currently working with stackblitz link https://stackblitz.com/edit/angular-x4a5b6-ng8m4z



Here in this demo see the file https://stackblitz.com/edit/angular-x4a5b6-ng8m4z?file=src%2Fapp%2Fquestion.service.ts



Where i am using the service call.. If i put async getQuestions() {}, it is giving error of questions.forEach of undefined



In service.ts



    jsonData: any = [
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_name",
"label": "Project Name",
"type": "text",
"value": "",
"required": false,
"minlength": 3,
"maxlength": 20,
"order": 1
},
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_desc",
"label": "Project Description",
"type": "text",
"value": "",
"required": true,
"order": 2
},
{
"elementType": "dropdown",
"key": 'project',
"label": 'Project Rating',
"options": ,
"order": 3
}
];

getQuestions() {

let questions: any = ;

//In the above JSON having empty values in "options": ,

this.jsonData.forEach(element => {
if (element.elementType === 'textbox') {
questions.push(new TextboxQuestion(element));
} else if (element.elementType === 'dropdown') {

//Need to push the data that comes from service result (res.data) to the options

questions.push(new DropdownQuestion(element));

console.log("step 1");

//The service which i call in real time..

// return this.http.get(element.optionsUrl).subscribe(res => {

//res.data has the following array, Using foreach pushing to elements.options.

// [
// { "key": 'average', "value": 'Average' },
// { "key": 'good', "value": 'Good' },
// { "key": 'great', "value": 'Great' }
// ],

// res.data.forEach(result => {
console.log("step 2");
// element.options.push(result);
// });
// console.log(element.options) give values as the above [
// { "key": 'average'...
console.log("step 3");
// console.log(element.options) give values as the above [
// { "key": 'average'...
// });
console.log("step 4");
//But here console.log(element.options) gives empty
}
});

return questions.sort((a, b) => a.order - b.order);
}









share|improve this question

























  • Not sure to understand the problem because it looks like you already have the solution: the service call is asynchronous so you'll get results in its callback (step 2 and 3). Here you can successfully fill array, so whatever you need to do with array, initiate it in the service callback.

    – Zim
    Nov 16 '18 at 13:34











  • I think this is basically just another duplicate of the old classic, stackoverflow.com/questions/14220321/…

    – misorude
    Nov 16 '18 at 13:34











  • @Zim, But if i console.log(array) in the place of step 4, then its giving empty array but in place of step 2 and 3, it giving value..

    – Maniraj from Karur
    Nov 16 '18 at 13:37











  • @undefined: yes, because at the time you reach step 4, the asynchronous call has not been finished yet!

    – Zim
    Nov 16 '18 at 13:44











  • put your result inside setTimeout

    – Chellappan
    Nov 16 '18 at 15:16














2












2








2








In my angular application, i am in the need to store the data to an array which will be empty at initial stage.



Example:



someFunction() {

let array = ;

console.log("step 1");

this.service.getRest(url).subscribe(result => {

result.data.forEach(element => {

console.log("step 2");

array.push(element); // Pushing all the objects comes from res.data

});

console.log("step 3");

});

console.log("step 4");

}


Here i have listed down the console.log() with step order.



In which the order while calling the function was,



Step 1
Step 4
Step 2
Step 3



Here after step 1, the step 4 calls and later the step 2.. So if i console.log(array) in place of step 4, it gives again empty array..



But in place of step 2 and 3 it gives value.. Coming out of the service the value is empty.



And hence always i am getting empty value in the array.



Kindly help me to store the data to the variable even though there is a time duration of service call and response coming back.



Tried by modifying code for a long time but couldn't get it worked..



Edit:



I have given below the real time application i am currently working with stackblitz link https://stackblitz.com/edit/angular-x4a5b6-ng8m4z



Here in this demo see the file https://stackblitz.com/edit/angular-x4a5b6-ng8m4z?file=src%2Fapp%2Fquestion.service.ts



Where i am using the service call.. If i put async getQuestions() {}, it is giving error of questions.forEach of undefined



In service.ts



    jsonData: any = [
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_name",
"label": "Project Name",
"type": "text",
"value": "",
"required": false,
"minlength": 3,
"maxlength": 20,
"order": 1
},
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_desc",
"label": "Project Description",
"type": "text",
"value": "",
"required": true,
"order": 2
},
{
"elementType": "dropdown",
"key": 'project',
"label": 'Project Rating',
"options": ,
"order": 3
}
];

getQuestions() {

let questions: any = ;

//In the above JSON having empty values in "options": ,

this.jsonData.forEach(element => {
if (element.elementType === 'textbox') {
questions.push(new TextboxQuestion(element));
} else if (element.elementType === 'dropdown') {

//Need to push the data that comes from service result (res.data) to the options

questions.push(new DropdownQuestion(element));

console.log("step 1");

//The service which i call in real time..

// return this.http.get(element.optionsUrl).subscribe(res => {

//res.data has the following array, Using foreach pushing to elements.options.

// [
// { "key": 'average', "value": 'Average' },
// { "key": 'good', "value": 'Good' },
// { "key": 'great', "value": 'Great' }
// ],

// res.data.forEach(result => {
console.log("step 2");
// element.options.push(result);
// });
// console.log(element.options) give values as the above [
// { "key": 'average'...
console.log("step 3");
// console.log(element.options) give values as the above [
// { "key": 'average'...
// });
console.log("step 4");
//But here console.log(element.options) gives empty
}
});

return questions.sort((a, b) => a.order - b.order);
}









share|improve this question
















In my angular application, i am in the need to store the data to an array which will be empty at initial stage.



Example:



someFunction() {

let array = ;

console.log("step 1");

this.service.getRest(url).subscribe(result => {

result.data.forEach(element => {

console.log("step 2");

array.push(element); // Pushing all the objects comes from res.data

});

console.log("step 3");

});

console.log("step 4");

}


Here i have listed down the console.log() with step order.



In which the order while calling the function was,



Step 1
Step 4
Step 2
Step 3



Here after step 1, the step 4 calls and later the step 2.. So if i console.log(array) in place of step 4, it gives again empty array..



But in place of step 2 and 3 it gives value.. Coming out of the service the value is empty.



And hence always i am getting empty value in the array.



Kindly help me to store the data to the variable even though there is a time duration of service call and response coming back.



Tried by modifying code for a long time but couldn't get it worked..



Edit:



I have given below the real time application i am currently working with stackblitz link https://stackblitz.com/edit/angular-x4a5b6-ng8m4z



Here in this demo see the file https://stackblitz.com/edit/angular-x4a5b6-ng8m4z?file=src%2Fapp%2Fquestion.service.ts



Where i am using the service call.. If i put async getQuestions() {}, it is giving error of questions.forEach of undefined



In service.ts



    jsonData: any = [
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_name",
"label": "Project Name",
"type": "text",
"value": "",
"required": false,
"minlength": 3,
"maxlength": 20,
"order": 1
},
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_desc",
"label": "Project Description",
"type": "text",
"value": "",
"required": true,
"order": 2
},
{
"elementType": "dropdown",
"key": 'project',
"label": 'Project Rating',
"options": ,
"order": 3
}
];

getQuestions() {

let questions: any = ;

//In the above JSON having empty values in "options": ,

this.jsonData.forEach(element => {
if (element.elementType === 'textbox') {
questions.push(new TextboxQuestion(element));
} else if (element.elementType === 'dropdown') {

//Need to push the data that comes from service result (res.data) to the options

questions.push(new DropdownQuestion(element));

console.log("step 1");

//The service which i call in real time..

// return this.http.get(element.optionsUrl).subscribe(res => {

//res.data has the following array, Using foreach pushing to elements.options.

// [
// { "key": 'average', "value": 'Average' },
// { "key": 'good', "value": 'Good' },
// { "key": 'great', "value": 'Great' }
// ],

// res.data.forEach(result => {
console.log("step 2");
// element.options.push(result);
// });
// console.log(element.options) give values as the above [
// { "key": 'average'...
console.log("step 3");
// console.log(element.options) give values as the above [
// { "key": 'average'...
// });
console.log("step 4");
//But here console.log(element.options) gives empty
}
});

return questions.sort((a, b) => a.order - b.order);
}






javascript angular typescript angular-services angular4-router






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 18:24







Maniraj from Karur

















asked Nov 16 '18 at 13:26









Maniraj from KarurManiraj from Karur

1,1351640




1,1351640













  • Not sure to understand the problem because it looks like you already have the solution: the service call is asynchronous so you'll get results in its callback (step 2 and 3). Here you can successfully fill array, so whatever you need to do with array, initiate it in the service callback.

    – Zim
    Nov 16 '18 at 13:34











  • I think this is basically just another duplicate of the old classic, stackoverflow.com/questions/14220321/…

    – misorude
    Nov 16 '18 at 13:34











  • @Zim, But if i console.log(array) in the place of step 4, then its giving empty array but in place of step 2 and 3, it giving value..

    – Maniraj from Karur
    Nov 16 '18 at 13:37











  • @undefined: yes, because at the time you reach step 4, the asynchronous call has not been finished yet!

    – Zim
    Nov 16 '18 at 13:44











  • put your result inside setTimeout

    – Chellappan
    Nov 16 '18 at 15:16



















  • Not sure to understand the problem because it looks like you already have the solution: the service call is asynchronous so you'll get results in its callback (step 2 and 3). Here you can successfully fill array, so whatever you need to do with array, initiate it in the service callback.

    – Zim
    Nov 16 '18 at 13:34











  • I think this is basically just another duplicate of the old classic, stackoverflow.com/questions/14220321/…

    – misorude
    Nov 16 '18 at 13:34











  • @Zim, But if i console.log(array) in the place of step 4, then its giving empty array but in place of step 2 and 3, it giving value..

    – Maniraj from Karur
    Nov 16 '18 at 13:37











  • @undefined: yes, because at the time you reach step 4, the asynchronous call has not been finished yet!

    – Zim
    Nov 16 '18 at 13:44











  • put your result inside setTimeout

    – Chellappan
    Nov 16 '18 at 15:16

















Not sure to understand the problem because it looks like you already have the solution: the service call is asynchronous so you'll get results in its callback (step 2 and 3). Here you can successfully fill array, so whatever you need to do with array, initiate it in the service callback.

– Zim
Nov 16 '18 at 13:34





Not sure to understand the problem because it looks like you already have the solution: the service call is asynchronous so you'll get results in its callback (step 2 and 3). Here you can successfully fill array, so whatever you need to do with array, initiate it in the service callback.

– Zim
Nov 16 '18 at 13:34













I think this is basically just another duplicate of the old classic, stackoverflow.com/questions/14220321/…

– misorude
Nov 16 '18 at 13:34





I think this is basically just another duplicate of the old classic, stackoverflow.com/questions/14220321/…

– misorude
Nov 16 '18 at 13:34













@Zim, But if i console.log(array) in the place of step 4, then its giving empty array but in place of step 2 and 3, it giving value..

– Maniraj from Karur
Nov 16 '18 at 13:37





@Zim, But if i console.log(array) in the place of step 4, then its giving empty array but in place of step 2 and 3, it giving value..

– Maniraj from Karur
Nov 16 '18 at 13:37













@undefined: yes, because at the time you reach step 4, the asynchronous call has not been finished yet!

– Zim
Nov 16 '18 at 13:44





@undefined: yes, because at the time you reach step 4, the asynchronous call has not been finished yet!

– Zim
Nov 16 '18 at 13:44













put your result inside setTimeout

– Chellappan
Nov 16 '18 at 15:16





put your result inside setTimeout

– Chellappan
Nov 16 '18 at 15:16












5 Answers
5






active

oldest

votes


















1














The first step if convert your function getQuestion in an Observable.



Why it is necesary? Because you need call to a this.http.get(element.optionsUrl). This is asyncronous (all http.get return observable). And you need wait to the called is finished to get the data. The good of observable is that inside "subscribe function" you have the data.



Therefore, we must thinking that the "services return observables, the component subscribe to the services".



Well, let the issue. The main problem is that we need several calls to http.get. As we know, all the calls to http are asyncronous, so how can be sure that we have all the data (remember that we only has the data into the subscribe function. As we don't want have several subscribe -the best is have no subscribe- in our service, we need use forkJoin. ForkJoin need an array of calls, and return an array of result.



So the fist is create an array of observable, then we return this array of observable. Wait a moment! we don't want return an array with the options, we want a observables of question. For this, in spite of return the array of observable, we return an object that use this array of observable. I put a simple example at bottom of the response



getQuestions():Observable<any> { //See that return an Observable

let questions: any = ;

//First we create an array of observables
let observables:Observable<any>=;
this.jsonData.forEach(element => {
if (element.elementType === 'dropdown') {
observables.push(this.http.get(element.optionsUrl))
}
}
//if only want return a forkjoin of observables we make
//return forkJoin(observables)
//But we want return an Observable of questions, so we use pipe(map)) to transform the response

return forkJoin(observables).pipe(map(res=>
{ //here we have and array like-yes is an array of array-
//with so many element as "dowpdown" we have in question
// res=[
// [{ "key": 'average', "value": 'Average' },...],
// [{ "key": 'car', "value": 'dog },...],
// ],
//as we have yet all the options, we can fullfit our questions
let index=0;
this.jsonData.forEach((element) => { //see that have two argument, the
//element and the "index"
if (element.elementType === 'textbox') {
questions.push(new TextboxQuestion(element));
} else if (element.elementType === 'dropdown') {
//here we give value to element.options
element.option=res[index];
questions.push(new DropdownQuestion(element));
index++;
}
})
return question
}))
}


NOTE: of how convert a function that return a value in observable using "of": Simple example



import { of} from 'rxjs';

getData():any
{
let data={property:"valor"}
return data;
}
getObservableData():Observable<any>
{
let data={property:"observable"}
return of(data);
}
getHttpData():Observable<any>
{
return this.httpClient.get("myUrl");
}
//A component can be call this functions as
let data=myService.getData();
console.log(data)
//See that the call to a getHttpData is equal than the call to getObservableData
//It is the reason becaouse we can "simulate" a httpClient.get call using "of"
myService.getObservableData().subscribe(res=>{
console.log(res);
}
myService.getHttpData().subscribe(res=>{
console.log(res);
}


NOTE2: use of forkJoin and map



getData()
{
let observables:Observables;

observables.push(of({property:"observable"});
observables.push(of({property:"observable2"});

return (forkJoin(observables).pipe(map(res=>{
//in res we have [{property:"observable"},{property:"observable2"}]
res.forEach((x,index)=>x.newProperty=i)
//in res we have [{property:"observable",newProperty:0},
// {property:"observable2",newProperty:1}]
}))
}


Update
There are other way to do the things. I think is better has a function that return the fullfilled "questions".



//You have
jsonData:any=....
//So you can have a function that return an observable
jsonData:any=...
getJsonData()
{
return of(this.jsonData)
}
//Well, what about to have a function thah return a fullFilled Data?
getFullFilledData()
{
let observables:Observables=;
this.jsonData.forEach(element => {
if (element.elementType === 'dropdown') {
observables.push(this.http.get(element.optionsUrl))
}
})
return forkJoin(observables).pipe(map(res=>
let index = 0;
this.jsonData.forEach((element) => {
if (element.elementType === 'dropdown') {
element.options = res[index];
index++;
}
})
return this.jsonData
}))
}


In this way you needn't change the component. If you call to getFullfilledData you have (in subscribe) the data



see a stackblitz






share|improve this answer


























  • Thanks Eliseo, You were too busy i think with your work.. I am in the need of in depth analysis in this solution i will have a go through it thoroughly..

    – Maniraj from Karur
    Nov 17 '18 at 12:39











  • @undefined, I update the answer to make the things more "razonables". I think is better have a function that return an observable of fullfilled data and not touch the component

    – Eliseo
    Nov 17 '18 at 13:00













  • Can you try out stackoverflow.com/questions/53357556/…

    – Maniraj from Karur
    Nov 18 '18 at 5:11











  • @undefined, Updated my answer adding a stackblitz and correct some errros. In the stackblitz you have a service that return a fullfilled Questions. Please, read the "README" file of the stackblitz to understand better what I've try to do. (the stackblitz only show the part of how read the questions from a file)

    – Eliseo
    Nov 18 '18 at 12:32











  • Thanks for your update will check over it..

    – Maniraj from Karur
    Nov 18 '18 at 12:45



















0














Your Step 4 is outside of the subscriptioon logic. Move it inside of it after Step 3 and it will be executed as last.



Observables send three types of notifications: next, error and complete.
https://angular.io/guide/observables
If you want to handle the positive Response, every logik has to be placed inside of the next notification.



myObservable.subscribe(
x => console.log('Observer got a next value: ' + x),
err => console.error('Observer got an error: ' + err),
() => console.log('Observer got a complete notification')
);


Flattening Strategies like the concatMap might also interest you, if you get several observables and want to handle them one after another.
https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b






share|improve this answer

































    0














    Your function is calling async API call so you will not able to get the value of array before or after your .subscribe() function. And you need to declare your array out of the function.



    And after that Simply you need to call another function if you get your data.



    let array = ;

    someFunction() {


    this.service.getRest(url).subscribe(result => {

    result.data.forEach(element => {

    array.push(element); // Pushing all the objects comes from res.data

    });

    this.anotherFunction();

    });

    anotherFunction()
    {
    console.log(this.array)//you can access it here
    }


    }






    share|improve this answer































      0














      Look at the following timeline:
      exec timeline



      There is no guarantee the service return will occur before step 4, hence no guarantee array will be filled in step 4.
      The recommended way to ensure working with a filled array is to move the array processing logic in the service callback, which will correspond to the second down arrow on the picture.






      share|improve this answer
























      • I have updated my question with angular stackblitz with real time working. Kindly help me to achieve the result..

        – Maniraj from Karur
        Nov 16 '18 at 15:08



















      0














      1-



      Well, here you can achieve the same result using different ways once there is a concrete use case, however in general you can try using async await:



      async someFunction() {
      this.asyncResult = await this.httpClient.get(yourUrl).toPromise();
      console.log("step 4");
      }


      You do not need to subscribe anymore, once data is fetched from “yourUrl”, Observable will be converted to promise and promise is resolved, then the returned data is stored in “asyncResult” variable. At that point the last console will be executed, here you'll find a little use case.



      PS: this.httpClient.get(yourUrl) is what is implemented in your this.service.getRest(url)





      2-



      Or merely move your console.log("step 4"); inside of the subscribe method scope to ensure the order. (Javascript has a famous asynchrounous behavior, google it for more details )






      share|improve this answer


























      • In my real application, i am having a forEach inside that function.. Inside the forEach only i am going to make service call.. If i give the async before function, then it is showing 'await' expression is only allowed within an async function. but outside foreach i am not getting error for await.. But inside foreach only i will get the URL for the service..

        – Maniraj from Karur
        Nov 16 '18 at 13:48











      • @undefined could you provide a little stackblitz please ?

        – selem mn
        Nov 16 '18 at 13:49











      • If i put async before function itself it gives error for me..

        – Maniraj from Karur
        Nov 16 '18 at 14:42











      • Give me seconds @undefined

        – selem mn
        Nov 16 '18 at 14:49











      • stackblitz.com/edit/angular-x4a5b6-ng8m4z The entire application flow i have explained.. Its working example..

        – Maniraj from Karur
        Nov 16 '18 at 14:58














      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53338806%2fhow-to-handle-data-comes-late-from-service%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      The first step if convert your function getQuestion in an Observable.



      Why it is necesary? Because you need call to a this.http.get(element.optionsUrl). This is asyncronous (all http.get return observable). And you need wait to the called is finished to get the data. The good of observable is that inside "subscribe function" you have the data.



      Therefore, we must thinking that the "services return observables, the component subscribe to the services".



      Well, let the issue. The main problem is that we need several calls to http.get. As we know, all the calls to http are asyncronous, so how can be sure that we have all the data (remember that we only has the data into the subscribe function. As we don't want have several subscribe -the best is have no subscribe- in our service, we need use forkJoin. ForkJoin need an array of calls, and return an array of result.



      So the fist is create an array of observable, then we return this array of observable. Wait a moment! we don't want return an array with the options, we want a observables of question. For this, in spite of return the array of observable, we return an object that use this array of observable. I put a simple example at bottom of the response



      getQuestions():Observable<any> { //See that return an Observable

      let questions: any = ;

      //First we create an array of observables
      let observables:Observable<any>=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      }
      //if only want return a forkjoin of observables we make
      //return forkJoin(observables)
      //But we want return an Observable of questions, so we use pipe(map)) to transform the response

      return forkJoin(observables).pipe(map(res=>
      { //here we have and array like-yes is an array of array-
      //with so many element as "dowpdown" we have in question
      // res=[
      // [{ "key": 'average', "value": 'Average' },...],
      // [{ "key": 'car', "value": 'dog },...],
      // ],
      //as we have yet all the options, we can fullfit our questions
      let index=0;
      this.jsonData.forEach((element) => { //see that have two argument, the
      //element and the "index"
      if (element.elementType === 'textbox') {
      questions.push(new TextboxQuestion(element));
      } else if (element.elementType === 'dropdown') {
      //here we give value to element.options
      element.option=res[index];
      questions.push(new DropdownQuestion(element));
      index++;
      }
      })
      return question
      }))
      }


      NOTE: of how convert a function that return a value in observable using "of": Simple example



      import { of} from 'rxjs';

      getData():any
      {
      let data={property:"valor"}
      return data;
      }
      getObservableData():Observable<any>
      {
      let data={property:"observable"}
      return of(data);
      }
      getHttpData():Observable<any>
      {
      return this.httpClient.get("myUrl");
      }
      //A component can be call this functions as
      let data=myService.getData();
      console.log(data)
      //See that the call to a getHttpData is equal than the call to getObservableData
      //It is the reason becaouse we can "simulate" a httpClient.get call using "of"
      myService.getObservableData().subscribe(res=>{
      console.log(res);
      }
      myService.getHttpData().subscribe(res=>{
      console.log(res);
      }


      NOTE2: use of forkJoin and map



      getData()
      {
      let observables:Observables;

      observables.push(of({property:"observable"});
      observables.push(of({property:"observable2"});

      return (forkJoin(observables).pipe(map(res=>{
      //in res we have [{property:"observable"},{property:"observable2"}]
      res.forEach((x,index)=>x.newProperty=i)
      //in res we have [{property:"observable",newProperty:0},
      // {property:"observable2",newProperty:1}]
      }))
      }


      Update
      There are other way to do the things. I think is better has a function that return the fullfilled "questions".



      //You have
      jsonData:any=....
      //So you can have a function that return an observable
      jsonData:any=...
      getJsonData()
      {
      return of(this.jsonData)
      }
      //Well, what about to have a function thah return a fullFilled Data?
      getFullFilledData()
      {
      let observables:Observables=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      })
      return forkJoin(observables).pipe(map(res=>
      let index = 0;
      this.jsonData.forEach((element) => {
      if (element.elementType === 'dropdown') {
      element.options = res[index];
      index++;
      }
      })
      return this.jsonData
      }))
      }


      In this way you needn't change the component. If you call to getFullfilledData you have (in subscribe) the data



      see a stackblitz






      share|improve this answer


























      • Thanks Eliseo, You were too busy i think with your work.. I am in the need of in depth analysis in this solution i will have a go through it thoroughly..

        – Maniraj from Karur
        Nov 17 '18 at 12:39











      • @undefined, I update the answer to make the things more "razonables". I think is better have a function that return an observable of fullfilled data and not touch the component

        – Eliseo
        Nov 17 '18 at 13:00













      • Can you try out stackoverflow.com/questions/53357556/…

        – Maniraj from Karur
        Nov 18 '18 at 5:11











      • @undefined, Updated my answer adding a stackblitz and correct some errros. In the stackblitz you have a service that return a fullfilled Questions. Please, read the "README" file of the stackblitz to understand better what I've try to do. (the stackblitz only show the part of how read the questions from a file)

        – Eliseo
        Nov 18 '18 at 12:32











      • Thanks for your update will check over it..

        – Maniraj from Karur
        Nov 18 '18 at 12:45
















      1














      The first step if convert your function getQuestion in an Observable.



      Why it is necesary? Because you need call to a this.http.get(element.optionsUrl). This is asyncronous (all http.get return observable). And you need wait to the called is finished to get the data. The good of observable is that inside "subscribe function" you have the data.



      Therefore, we must thinking that the "services return observables, the component subscribe to the services".



      Well, let the issue. The main problem is that we need several calls to http.get. As we know, all the calls to http are asyncronous, so how can be sure that we have all the data (remember that we only has the data into the subscribe function. As we don't want have several subscribe -the best is have no subscribe- in our service, we need use forkJoin. ForkJoin need an array of calls, and return an array of result.



      So the fist is create an array of observable, then we return this array of observable. Wait a moment! we don't want return an array with the options, we want a observables of question. For this, in spite of return the array of observable, we return an object that use this array of observable. I put a simple example at bottom of the response



      getQuestions():Observable<any> { //See that return an Observable

      let questions: any = ;

      //First we create an array of observables
      let observables:Observable<any>=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      }
      //if only want return a forkjoin of observables we make
      //return forkJoin(observables)
      //But we want return an Observable of questions, so we use pipe(map)) to transform the response

      return forkJoin(observables).pipe(map(res=>
      { //here we have and array like-yes is an array of array-
      //with so many element as "dowpdown" we have in question
      // res=[
      // [{ "key": 'average', "value": 'Average' },...],
      // [{ "key": 'car', "value": 'dog },...],
      // ],
      //as we have yet all the options, we can fullfit our questions
      let index=0;
      this.jsonData.forEach((element) => { //see that have two argument, the
      //element and the "index"
      if (element.elementType === 'textbox') {
      questions.push(new TextboxQuestion(element));
      } else if (element.elementType === 'dropdown') {
      //here we give value to element.options
      element.option=res[index];
      questions.push(new DropdownQuestion(element));
      index++;
      }
      })
      return question
      }))
      }


      NOTE: of how convert a function that return a value in observable using "of": Simple example



      import { of} from 'rxjs';

      getData():any
      {
      let data={property:"valor"}
      return data;
      }
      getObservableData():Observable<any>
      {
      let data={property:"observable"}
      return of(data);
      }
      getHttpData():Observable<any>
      {
      return this.httpClient.get("myUrl");
      }
      //A component can be call this functions as
      let data=myService.getData();
      console.log(data)
      //See that the call to a getHttpData is equal than the call to getObservableData
      //It is the reason becaouse we can "simulate" a httpClient.get call using "of"
      myService.getObservableData().subscribe(res=>{
      console.log(res);
      }
      myService.getHttpData().subscribe(res=>{
      console.log(res);
      }


      NOTE2: use of forkJoin and map



      getData()
      {
      let observables:Observables;

      observables.push(of({property:"observable"});
      observables.push(of({property:"observable2"});

      return (forkJoin(observables).pipe(map(res=>{
      //in res we have [{property:"observable"},{property:"observable2"}]
      res.forEach((x,index)=>x.newProperty=i)
      //in res we have [{property:"observable",newProperty:0},
      // {property:"observable2",newProperty:1}]
      }))
      }


      Update
      There are other way to do the things. I think is better has a function that return the fullfilled "questions".



      //You have
      jsonData:any=....
      //So you can have a function that return an observable
      jsonData:any=...
      getJsonData()
      {
      return of(this.jsonData)
      }
      //Well, what about to have a function thah return a fullFilled Data?
      getFullFilledData()
      {
      let observables:Observables=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      })
      return forkJoin(observables).pipe(map(res=>
      let index = 0;
      this.jsonData.forEach((element) => {
      if (element.elementType === 'dropdown') {
      element.options = res[index];
      index++;
      }
      })
      return this.jsonData
      }))
      }


      In this way you needn't change the component. If you call to getFullfilledData you have (in subscribe) the data



      see a stackblitz






      share|improve this answer


























      • Thanks Eliseo, You were too busy i think with your work.. I am in the need of in depth analysis in this solution i will have a go through it thoroughly..

        – Maniraj from Karur
        Nov 17 '18 at 12:39











      • @undefined, I update the answer to make the things more "razonables". I think is better have a function that return an observable of fullfilled data and not touch the component

        – Eliseo
        Nov 17 '18 at 13:00













      • Can you try out stackoverflow.com/questions/53357556/…

        – Maniraj from Karur
        Nov 18 '18 at 5:11











      • @undefined, Updated my answer adding a stackblitz and correct some errros. In the stackblitz you have a service that return a fullfilled Questions. Please, read the "README" file of the stackblitz to understand better what I've try to do. (the stackblitz only show the part of how read the questions from a file)

        – Eliseo
        Nov 18 '18 at 12:32











      • Thanks for your update will check over it..

        – Maniraj from Karur
        Nov 18 '18 at 12:45














      1












      1








      1







      The first step if convert your function getQuestion in an Observable.



      Why it is necesary? Because you need call to a this.http.get(element.optionsUrl). This is asyncronous (all http.get return observable). And you need wait to the called is finished to get the data. The good of observable is that inside "subscribe function" you have the data.



      Therefore, we must thinking that the "services return observables, the component subscribe to the services".



      Well, let the issue. The main problem is that we need several calls to http.get. As we know, all the calls to http are asyncronous, so how can be sure that we have all the data (remember that we only has the data into the subscribe function. As we don't want have several subscribe -the best is have no subscribe- in our service, we need use forkJoin. ForkJoin need an array of calls, and return an array of result.



      So the fist is create an array of observable, then we return this array of observable. Wait a moment! we don't want return an array with the options, we want a observables of question. For this, in spite of return the array of observable, we return an object that use this array of observable. I put a simple example at bottom of the response



      getQuestions():Observable<any> { //See that return an Observable

      let questions: any = ;

      //First we create an array of observables
      let observables:Observable<any>=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      }
      //if only want return a forkjoin of observables we make
      //return forkJoin(observables)
      //But we want return an Observable of questions, so we use pipe(map)) to transform the response

      return forkJoin(observables).pipe(map(res=>
      { //here we have and array like-yes is an array of array-
      //with so many element as "dowpdown" we have in question
      // res=[
      // [{ "key": 'average', "value": 'Average' },...],
      // [{ "key": 'car', "value": 'dog },...],
      // ],
      //as we have yet all the options, we can fullfit our questions
      let index=0;
      this.jsonData.forEach((element) => { //see that have two argument, the
      //element and the "index"
      if (element.elementType === 'textbox') {
      questions.push(new TextboxQuestion(element));
      } else if (element.elementType === 'dropdown') {
      //here we give value to element.options
      element.option=res[index];
      questions.push(new DropdownQuestion(element));
      index++;
      }
      })
      return question
      }))
      }


      NOTE: of how convert a function that return a value in observable using "of": Simple example



      import { of} from 'rxjs';

      getData():any
      {
      let data={property:"valor"}
      return data;
      }
      getObservableData():Observable<any>
      {
      let data={property:"observable"}
      return of(data);
      }
      getHttpData():Observable<any>
      {
      return this.httpClient.get("myUrl");
      }
      //A component can be call this functions as
      let data=myService.getData();
      console.log(data)
      //See that the call to a getHttpData is equal than the call to getObservableData
      //It is the reason becaouse we can "simulate" a httpClient.get call using "of"
      myService.getObservableData().subscribe(res=>{
      console.log(res);
      }
      myService.getHttpData().subscribe(res=>{
      console.log(res);
      }


      NOTE2: use of forkJoin and map



      getData()
      {
      let observables:Observables;

      observables.push(of({property:"observable"});
      observables.push(of({property:"observable2"});

      return (forkJoin(observables).pipe(map(res=>{
      //in res we have [{property:"observable"},{property:"observable2"}]
      res.forEach((x,index)=>x.newProperty=i)
      //in res we have [{property:"observable",newProperty:0},
      // {property:"observable2",newProperty:1}]
      }))
      }


      Update
      There are other way to do the things. I think is better has a function that return the fullfilled "questions".



      //You have
      jsonData:any=....
      //So you can have a function that return an observable
      jsonData:any=...
      getJsonData()
      {
      return of(this.jsonData)
      }
      //Well, what about to have a function thah return a fullFilled Data?
      getFullFilledData()
      {
      let observables:Observables=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      })
      return forkJoin(observables).pipe(map(res=>
      let index = 0;
      this.jsonData.forEach((element) => {
      if (element.elementType === 'dropdown') {
      element.options = res[index];
      index++;
      }
      })
      return this.jsonData
      }))
      }


      In this way you needn't change the component. If you call to getFullfilledData you have (in subscribe) the data



      see a stackblitz






      share|improve this answer















      The first step if convert your function getQuestion in an Observable.



      Why it is necesary? Because you need call to a this.http.get(element.optionsUrl). This is asyncronous (all http.get return observable). And you need wait to the called is finished to get the data. The good of observable is that inside "subscribe function" you have the data.



      Therefore, we must thinking that the "services return observables, the component subscribe to the services".



      Well, let the issue. The main problem is that we need several calls to http.get. As we know, all the calls to http are asyncronous, so how can be sure that we have all the data (remember that we only has the data into the subscribe function. As we don't want have several subscribe -the best is have no subscribe- in our service, we need use forkJoin. ForkJoin need an array of calls, and return an array of result.



      So the fist is create an array of observable, then we return this array of observable. Wait a moment! we don't want return an array with the options, we want a observables of question. For this, in spite of return the array of observable, we return an object that use this array of observable. I put a simple example at bottom of the response



      getQuestions():Observable<any> { //See that return an Observable

      let questions: any = ;

      //First we create an array of observables
      let observables:Observable<any>=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      }
      //if only want return a forkjoin of observables we make
      //return forkJoin(observables)
      //But we want return an Observable of questions, so we use pipe(map)) to transform the response

      return forkJoin(observables).pipe(map(res=>
      { //here we have and array like-yes is an array of array-
      //with so many element as "dowpdown" we have in question
      // res=[
      // [{ "key": 'average', "value": 'Average' },...],
      // [{ "key": 'car', "value": 'dog },...],
      // ],
      //as we have yet all the options, we can fullfit our questions
      let index=0;
      this.jsonData.forEach((element) => { //see that have two argument, the
      //element and the "index"
      if (element.elementType === 'textbox') {
      questions.push(new TextboxQuestion(element));
      } else if (element.elementType === 'dropdown') {
      //here we give value to element.options
      element.option=res[index];
      questions.push(new DropdownQuestion(element));
      index++;
      }
      })
      return question
      }))
      }


      NOTE: of how convert a function that return a value in observable using "of": Simple example



      import { of} from 'rxjs';

      getData():any
      {
      let data={property:"valor"}
      return data;
      }
      getObservableData():Observable<any>
      {
      let data={property:"observable"}
      return of(data);
      }
      getHttpData():Observable<any>
      {
      return this.httpClient.get("myUrl");
      }
      //A component can be call this functions as
      let data=myService.getData();
      console.log(data)
      //See that the call to a getHttpData is equal than the call to getObservableData
      //It is the reason becaouse we can "simulate" a httpClient.get call using "of"
      myService.getObservableData().subscribe(res=>{
      console.log(res);
      }
      myService.getHttpData().subscribe(res=>{
      console.log(res);
      }


      NOTE2: use of forkJoin and map



      getData()
      {
      let observables:Observables;

      observables.push(of({property:"observable"});
      observables.push(of({property:"observable2"});

      return (forkJoin(observables).pipe(map(res=>{
      //in res we have [{property:"observable"},{property:"observable2"}]
      res.forEach((x,index)=>x.newProperty=i)
      //in res we have [{property:"observable",newProperty:0},
      // {property:"observable2",newProperty:1}]
      }))
      }


      Update
      There are other way to do the things. I think is better has a function that return the fullfilled "questions".



      //You have
      jsonData:any=....
      //So you can have a function that return an observable
      jsonData:any=...
      getJsonData()
      {
      return of(this.jsonData)
      }
      //Well, what about to have a function thah return a fullFilled Data?
      getFullFilledData()
      {
      let observables:Observables=;
      this.jsonData.forEach(element => {
      if (element.elementType === 'dropdown') {
      observables.push(this.http.get(element.optionsUrl))
      }
      })
      return forkJoin(observables).pipe(map(res=>
      let index = 0;
      this.jsonData.forEach((element) => {
      if (element.elementType === 'dropdown') {
      element.options = res[index];
      index++;
      }
      })
      return this.jsonData
      }))
      }


      In this way you needn't change the component. If you call to getFullfilledData you have (in subscribe) the data



      see a stackblitz







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 18 '18 at 12:24

























      answered Nov 17 '18 at 12:27









      EliseoEliseo

      7,0591314




      7,0591314













      • Thanks Eliseo, You were too busy i think with your work.. I am in the need of in depth analysis in this solution i will have a go through it thoroughly..

        – Maniraj from Karur
        Nov 17 '18 at 12:39











      • @undefined, I update the answer to make the things more "razonables". I think is better have a function that return an observable of fullfilled data and not touch the component

        – Eliseo
        Nov 17 '18 at 13:00













      • Can you try out stackoverflow.com/questions/53357556/…

        – Maniraj from Karur
        Nov 18 '18 at 5:11











      • @undefined, Updated my answer adding a stackblitz and correct some errros. In the stackblitz you have a service that return a fullfilled Questions. Please, read the "README" file of the stackblitz to understand better what I've try to do. (the stackblitz only show the part of how read the questions from a file)

        – Eliseo
        Nov 18 '18 at 12:32











      • Thanks for your update will check over it..

        – Maniraj from Karur
        Nov 18 '18 at 12:45



















      • Thanks Eliseo, You were too busy i think with your work.. I am in the need of in depth analysis in this solution i will have a go through it thoroughly..

        – Maniraj from Karur
        Nov 17 '18 at 12:39











      • @undefined, I update the answer to make the things more "razonables". I think is better have a function that return an observable of fullfilled data and not touch the component

        – Eliseo
        Nov 17 '18 at 13:00













      • Can you try out stackoverflow.com/questions/53357556/…

        – Maniraj from Karur
        Nov 18 '18 at 5:11











      • @undefined, Updated my answer adding a stackblitz and correct some errros. In the stackblitz you have a service that return a fullfilled Questions. Please, read the "README" file of the stackblitz to understand better what I've try to do. (the stackblitz only show the part of how read the questions from a file)

        – Eliseo
        Nov 18 '18 at 12:32











      • Thanks for your update will check over it..

        – Maniraj from Karur
        Nov 18 '18 at 12:45

















      Thanks Eliseo, You were too busy i think with your work.. I am in the need of in depth analysis in this solution i will have a go through it thoroughly..

      – Maniraj from Karur
      Nov 17 '18 at 12:39





      Thanks Eliseo, You were too busy i think with your work.. I am in the need of in depth analysis in this solution i will have a go through it thoroughly..

      – Maniraj from Karur
      Nov 17 '18 at 12:39













      @undefined, I update the answer to make the things more "razonables". I think is better have a function that return an observable of fullfilled data and not touch the component

      – Eliseo
      Nov 17 '18 at 13:00







      @undefined, I update the answer to make the things more "razonables". I think is better have a function that return an observable of fullfilled data and not touch the component

      – Eliseo
      Nov 17 '18 at 13:00















      Can you try out stackoverflow.com/questions/53357556/…

      – Maniraj from Karur
      Nov 18 '18 at 5:11





      Can you try out stackoverflow.com/questions/53357556/…

      – Maniraj from Karur
      Nov 18 '18 at 5:11













      @undefined, Updated my answer adding a stackblitz and correct some errros. In the stackblitz you have a service that return a fullfilled Questions. Please, read the "README" file of the stackblitz to understand better what I've try to do. (the stackblitz only show the part of how read the questions from a file)

      – Eliseo
      Nov 18 '18 at 12:32





      @undefined, Updated my answer adding a stackblitz and correct some errros. In the stackblitz you have a service that return a fullfilled Questions. Please, read the "README" file of the stackblitz to understand better what I've try to do. (the stackblitz only show the part of how read the questions from a file)

      – Eliseo
      Nov 18 '18 at 12:32













      Thanks for your update will check over it..

      – Maniraj from Karur
      Nov 18 '18 at 12:45





      Thanks for your update will check over it..

      – Maniraj from Karur
      Nov 18 '18 at 12:45













      0














      Your Step 4 is outside of the subscriptioon logic. Move it inside of it after Step 3 and it will be executed as last.



      Observables send three types of notifications: next, error and complete.
      https://angular.io/guide/observables
      If you want to handle the positive Response, every logik has to be placed inside of the next notification.



      myObservable.subscribe(
      x => console.log('Observer got a next value: ' + x),
      err => console.error('Observer got an error: ' + err),
      () => console.log('Observer got a complete notification')
      );


      Flattening Strategies like the concatMap might also interest you, if you get several observables and want to handle them one after another.
      https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b






      share|improve this answer






























        0














        Your Step 4 is outside of the subscriptioon logic. Move it inside of it after Step 3 and it will be executed as last.



        Observables send three types of notifications: next, error and complete.
        https://angular.io/guide/observables
        If you want to handle the positive Response, every logik has to be placed inside of the next notification.



        myObservable.subscribe(
        x => console.log('Observer got a next value: ' + x),
        err => console.error('Observer got an error: ' + err),
        () => console.log('Observer got a complete notification')
        );


        Flattening Strategies like the concatMap might also interest you, if you get several observables and want to handle them one after another.
        https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b






        share|improve this answer




























          0












          0








          0







          Your Step 4 is outside of the subscriptioon logic. Move it inside of it after Step 3 and it will be executed as last.



          Observables send three types of notifications: next, error and complete.
          https://angular.io/guide/observables
          If you want to handle the positive Response, every logik has to be placed inside of the next notification.



          myObservable.subscribe(
          x => console.log('Observer got a next value: ' + x),
          err => console.error('Observer got an error: ' + err),
          () => console.log('Observer got a complete notification')
          );


          Flattening Strategies like the concatMap might also interest you, if you get several observables and want to handle them one after another.
          https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b






          share|improve this answer















          Your Step 4 is outside of the subscriptioon logic. Move it inside of it after Step 3 and it will be executed as last.



          Observables send three types of notifications: next, error and complete.
          https://angular.io/guide/observables
          If you want to handle the positive Response, every logik has to be placed inside of the next notification.



          myObservable.subscribe(
          x => console.log('Observer got a next value: ' + x),
          err => console.error('Observer got an error: ' + err),
          () => console.log('Observer got a complete notification')
          );


          Flattening Strategies like the concatMap might also interest you, if you get several observables and want to handle them one after another.
          https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 16 '18 at 13:38

























          answered Nov 16 '18 at 13:32









          Severin KlugSeverin Klug

          424




          424























              0














              Your function is calling async API call so you will not able to get the value of array before or after your .subscribe() function. And you need to declare your array out of the function.



              And after that Simply you need to call another function if you get your data.



              let array = ;

              someFunction() {


              this.service.getRest(url).subscribe(result => {

              result.data.forEach(element => {

              array.push(element); // Pushing all the objects comes from res.data

              });

              this.anotherFunction();

              });

              anotherFunction()
              {
              console.log(this.array)//you can access it here
              }


              }






              share|improve this answer




























                0














                Your function is calling async API call so you will not able to get the value of array before or after your .subscribe() function. And you need to declare your array out of the function.



                And after that Simply you need to call another function if you get your data.



                let array = ;

                someFunction() {


                this.service.getRest(url).subscribe(result => {

                result.data.forEach(element => {

                array.push(element); // Pushing all the objects comes from res.data

                });

                this.anotherFunction();

                });

                anotherFunction()
                {
                console.log(this.array)//you can access it here
                }


                }






                share|improve this answer


























                  0












                  0








                  0







                  Your function is calling async API call so you will not able to get the value of array before or after your .subscribe() function. And you need to declare your array out of the function.



                  And after that Simply you need to call another function if you get your data.



                  let array = ;

                  someFunction() {


                  this.service.getRest(url).subscribe(result => {

                  result.data.forEach(element => {

                  array.push(element); // Pushing all the objects comes from res.data

                  });

                  this.anotherFunction();

                  });

                  anotherFunction()
                  {
                  console.log(this.array)//you can access it here
                  }


                  }






                  share|improve this answer













                  Your function is calling async API call so you will not able to get the value of array before or after your .subscribe() function. And you need to declare your array out of the function.



                  And after that Simply you need to call another function if you get your data.



                  let array = ;

                  someFunction() {


                  this.service.getRest(url).subscribe(result => {

                  result.data.forEach(element => {

                  array.push(element); // Pushing all the objects comes from res.data

                  });

                  this.anotherFunction();

                  });

                  anotherFunction()
                  {
                  console.log(this.array)//you can access it here
                  }


                  }







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 16 '18 at 13:47









                  DipalDipal

                  1617




                  1617























                      0














                      Look at the following timeline:
                      exec timeline



                      There is no guarantee the service return will occur before step 4, hence no guarantee array will be filled in step 4.
                      The recommended way to ensure working with a filled array is to move the array processing logic in the service callback, which will correspond to the second down arrow on the picture.






                      share|improve this answer
























                      • I have updated my question with angular stackblitz with real time working. Kindly help me to achieve the result..

                        – Maniraj from Karur
                        Nov 16 '18 at 15:08
















                      0














                      Look at the following timeline:
                      exec timeline



                      There is no guarantee the service return will occur before step 4, hence no guarantee array will be filled in step 4.
                      The recommended way to ensure working with a filled array is to move the array processing logic in the service callback, which will correspond to the second down arrow on the picture.






                      share|improve this answer
























                      • I have updated my question with angular stackblitz with real time working. Kindly help me to achieve the result..

                        – Maniraj from Karur
                        Nov 16 '18 at 15:08














                      0












                      0








                      0







                      Look at the following timeline:
                      exec timeline



                      There is no guarantee the service return will occur before step 4, hence no guarantee array will be filled in step 4.
                      The recommended way to ensure working with a filled array is to move the array processing logic in the service callback, which will correspond to the second down arrow on the picture.






                      share|improve this answer













                      Look at the following timeline:
                      exec timeline



                      There is no guarantee the service return will occur before step 4, hence no guarantee array will be filled in step 4.
                      The recommended way to ensure working with a filled array is to move the array processing logic in the service callback, which will correspond to the second down arrow on the picture.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Nov 16 '18 at 14:01









                      ZimZim

                      1,0741817




                      1,0741817













                      • I have updated my question with angular stackblitz with real time working. Kindly help me to achieve the result..

                        – Maniraj from Karur
                        Nov 16 '18 at 15:08



















                      • I have updated my question with angular stackblitz with real time working. Kindly help me to achieve the result..

                        – Maniraj from Karur
                        Nov 16 '18 at 15:08

















                      I have updated my question with angular stackblitz with real time working. Kindly help me to achieve the result..

                      – Maniraj from Karur
                      Nov 16 '18 at 15:08





                      I have updated my question with angular stackblitz with real time working. Kindly help me to achieve the result..

                      – Maniraj from Karur
                      Nov 16 '18 at 15:08











                      0














                      1-



                      Well, here you can achieve the same result using different ways once there is a concrete use case, however in general you can try using async await:



                      async someFunction() {
                      this.asyncResult = await this.httpClient.get(yourUrl).toPromise();
                      console.log("step 4");
                      }


                      You do not need to subscribe anymore, once data is fetched from “yourUrl”, Observable will be converted to promise and promise is resolved, then the returned data is stored in “asyncResult” variable. At that point the last console will be executed, here you'll find a little use case.



                      PS: this.httpClient.get(yourUrl) is what is implemented in your this.service.getRest(url)





                      2-



                      Or merely move your console.log("step 4"); inside of the subscribe method scope to ensure the order. (Javascript has a famous asynchrounous behavior, google it for more details )






                      share|improve this answer


























                      • In my real application, i am having a forEach inside that function.. Inside the forEach only i am going to make service call.. If i give the async before function, then it is showing 'await' expression is only allowed within an async function. but outside foreach i am not getting error for await.. But inside foreach only i will get the URL for the service..

                        – Maniraj from Karur
                        Nov 16 '18 at 13:48











                      • @undefined could you provide a little stackblitz please ?

                        – selem mn
                        Nov 16 '18 at 13:49











                      • If i put async before function itself it gives error for me..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:42











                      • Give me seconds @undefined

                        – selem mn
                        Nov 16 '18 at 14:49











                      • stackblitz.com/edit/angular-x4a5b6-ng8m4z The entire application flow i have explained.. Its working example..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:58


















                      0














                      1-



                      Well, here you can achieve the same result using different ways once there is a concrete use case, however in general you can try using async await:



                      async someFunction() {
                      this.asyncResult = await this.httpClient.get(yourUrl).toPromise();
                      console.log("step 4");
                      }


                      You do not need to subscribe anymore, once data is fetched from “yourUrl”, Observable will be converted to promise and promise is resolved, then the returned data is stored in “asyncResult” variable. At that point the last console will be executed, here you'll find a little use case.



                      PS: this.httpClient.get(yourUrl) is what is implemented in your this.service.getRest(url)





                      2-



                      Or merely move your console.log("step 4"); inside of the subscribe method scope to ensure the order. (Javascript has a famous asynchrounous behavior, google it for more details )






                      share|improve this answer


























                      • In my real application, i am having a forEach inside that function.. Inside the forEach only i am going to make service call.. If i give the async before function, then it is showing 'await' expression is only allowed within an async function. but outside foreach i am not getting error for await.. But inside foreach only i will get the URL for the service..

                        – Maniraj from Karur
                        Nov 16 '18 at 13:48











                      • @undefined could you provide a little stackblitz please ?

                        – selem mn
                        Nov 16 '18 at 13:49











                      • If i put async before function itself it gives error for me..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:42











                      • Give me seconds @undefined

                        – selem mn
                        Nov 16 '18 at 14:49











                      • stackblitz.com/edit/angular-x4a5b6-ng8m4z The entire application flow i have explained.. Its working example..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:58
















                      0












                      0








                      0







                      1-



                      Well, here you can achieve the same result using different ways once there is a concrete use case, however in general you can try using async await:



                      async someFunction() {
                      this.asyncResult = await this.httpClient.get(yourUrl).toPromise();
                      console.log("step 4");
                      }


                      You do not need to subscribe anymore, once data is fetched from “yourUrl”, Observable will be converted to promise and promise is resolved, then the returned data is stored in “asyncResult” variable. At that point the last console will be executed, here you'll find a little use case.



                      PS: this.httpClient.get(yourUrl) is what is implemented in your this.service.getRest(url)





                      2-



                      Or merely move your console.log("step 4"); inside of the subscribe method scope to ensure the order. (Javascript has a famous asynchrounous behavior, google it for more details )






                      share|improve this answer















                      1-



                      Well, here you can achieve the same result using different ways once there is a concrete use case, however in general you can try using async await:



                      async someFunction() {
                      this.asyncResult = await this.httpClient.get(yourUrl).toPromise();
                      console.log("step 4");
                      }


                      You do not need to subscribe anymore, once data is fetched from “yourUrl”, Observable will be converted to promise and promise is resolved, then the returned data is stored in “asyncResult” variable. At that point the last console will be executed, here you'll find a little use case.



                      PS: this.httpClient.get(yourUrl) is what is implemented in your this.service.getRest(url)





                      2-



                      Or merely move your console.log("step 4"); inside of the subscribe method scope to ensure the order. (Javascript has a famous asynchrounous behavior, google it for more details )







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Nov 16 '18 at 16:09

























                      answered Nov 16 '18 at 13:40









                      selem mnselem mn

                      5,23542040




                      5,23542040













                      • In my real application, i am having a forEach inside that function.. Inside the forEach only i am going to make service call.. If i give the async before function, then it is showing 'await' expression is only allowed within an async function. but outside foreach i am not getting error for await.. But inside foreach only i will get the URL for the service..

                        – Maniraj from Karur
                        Nov 16 '18 at 13:48











                      • @undefined could you provide a little stackblitz please ?

                        – selem mn
                        Nov 16 '18 at 13:49











                      • If i put async before function itself it gives error for me..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:42











                      • Give me seconds @undefined

                        – selem mn
                        Nov 16 '18 at 14:49











                      • stackblitz.com/edit/angular-x4a5b6-ng8m4z The entire application flow i have explained.. Its working example..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:58





















                      • In my real application, i am having a forEach inside that function.. Inside the forEach only i am going to make service call.. If i give the async before function, then it is showing 'await' expression is only allowed within an async function. but outside foreach i am not getting error for await.. But inside foreach only i will get the URL for the service..

                        – Maniraj from Karur
                        Nov 16 '18 at 13:48











                      • @undefined could you provide a little stackblitz please ?

                        – selem mn
                        Nov 16 '18 at 13:49











                      • If i put async before function itself it gives error for me..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:42











                      • Give me seconds @undefined

                        – selem mn
                        Nov 16 '18 at 14:49











                      • stackblitz.com/edit/angular-x4a5b6-ng8m4z The entire application flow i have explained.. Its working example..

                        – Maniraj from Karur
                        Nov 16 '18 at 14:58



















                      In my real application, i am having a forEach inside that function.. Inside the forEach only i am going to make service call.. If i give the async before function, then it is showing 'await' expression is only allowed within an async function. but outside foreach i am not getting error for await.. But inside foreach only i will get the URL for the service..

                      – Maniraj from Karur
                      Nov 16 '18 at 13:48





                      In my real application, i am having a forEach inside that function.. Inside the forEach only i am going to make service call.. If i give the async before function, then it is showing 'await' expression is only allowed within an async function. but outside foreach i am not getting error for await.. But inside foreach only i will get the URL for the service..

                      – Maniraj from Karur
                      Nov 16 '18 at 13:48













                      @undefined could you provide a little stackblitz please ?

                      – selem mn
                      Nov 16 '18 at 13:49





                      @undefined could you provide a little stackblitz please ?

                      – selem mn
                      Nov 16 '18 at 13:49













                      If i put async before function itself it gives error for me..

                      – Maniraj from Karur
                      Nov 16 '18 at 14:42





                      If i put async before function itself it gives error for me..

                      – Maniraj from Karur
                      Nov 16 '18 at 14:42













                      Give me seconds @undefined

                      – selem mn
                      Nov 16 '18 at 14:49





                      Give me seconds @undefined

                      – selem mn
                      Nov 16 '18 at 14:49













                      stackblitz.com/edit/angular-x4a5b6-ng8m4z The entire application flow i have explained.. Its working example..

                      – Maniraj from Karur
                      Nov 16 '18 at 14:58







                      stackblitz.com/edit/angular-x4a5b6-ng8m4z The entire application flow i have explained.. Its working example..

                      – Maniraj from Karur
                      Nov 16 '18 at 14:58




















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53338806%2fhow-to-handle-data-comes-late-from-service%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Xamarin.iOS Cant Deploy on Iphone

                      Glorious Revolution

                      Dulmage-Mendelsohn matrix decomposition in Python