Suggested Videos
Part 37 - Angular router navigate method | Text | Slides
Part 38 - Promises in angular 2 example | Text | Slides
Part 39 - Angular promises vs observables | Text | Slides
In this video we will how to resubscribe and retry an Observable if there is an error.
Please change getEmployeeByCode() method in employee.service.ts file to return an Observable instead of a Promise as shown below.
To cause an error, stop the Web API Service. At this point if you navigate to http://localhost:12345/src/employees/emp101, the application display a message stating - Problem with the service. Please try again after sometime. In the "Console" tab of the "Browser Developer Tools" you will see - ERR_CONNECTION_REFUSED.
To resubscribe to the Observable and retry, use the rxjs retry operator. The changes in employee.component.ts file are commented and self explanatory.
The downside of this approach is that the application keeps on retrying forever. If we start the Web API service, the call succeeds and the observable completes with employee data displayed on the web page.
Now if your requirement is not to retry forever, but only retry for a specific number of times if there is an error then we can use another variation of retry as shown below. Notice in this case we are passing number 3 to the retry opertaor indicating that we only want to retry 3 times. After the 3rd attempt the observable completes with an error.
The problem with the retry operator is that, it immidiately retries when there is an error. In our case it is a connection issue with the service. Retrying again immediately in our case does not make much sense, as most likely it might fail again. So in situations like this we may want to retry after a short delay, may be after a second or so. This is when we use the retryWhen rxjs operator. retryWhen operator allows us to specify delay in milli-seconds and can be used as shown below. Please donot forget to import retryWhen and delay operators.
Now if you are wondering can't we use delay opertor with retry operator, the answer is NO, we can't. The delay operator in the following example will not work as expected. As you can see from the browser console, it immediately retries instead of waiting for 5 seconds before a retry attempt.
If you want to retry every 1000 milli-seconds only for a miximum of 5 times then we can use rxjs scan operator along with the take operator. While retrying we also want to show the retry attempt number to the user on the web page as shown below.
After all the retry attempts are exhausted, the application should stop retrying and display the error message to the user as shown below.
If the connection becomes available between the retry attempts, the application should display employee data.
Here is the complete code.
In our next video, we will discuss how to allow the end user to cancel retry attempts at any point using the unsubscribe method.
Part 37 - Angular router navigate method | Text | Slides
Part 38 - Promises in angular 2 example | Text | Slides
Part 39 - Angular promises vs observables | Text | Slides
In this video we will how to resubscribe and retry an Observable if there is an error.
Please change getEmployeeByCode() method in employee.service.ts file to return an Observable instead of a Promise as shown below.
getEmployeeByCode(empCode:
string):
Observable<IEmployee> {
return this._http.get("http://localhost:24535/api/employees/" + empCode)
.map((response: Response) =>
<IEmployee>response.json())
.catch(this.handleError);
}
To cause an error, stop the Web API Service. At this point if you navigate to http://localhost:12345/src/employees/emp101, the application display a message stating - Problem with the service. Please try again after sometime. In the "Console" tab of the "Browser Developer Tools" you will see - ERR_CONNECTION_REFUSED.
To resubscribe to the Observable and retry, use the rxjs retry operator. The changes in employee.component.ts file are commented and self explanatory.
import { Component, OnInit } from '@angular/core';
import { IEmployee } from './employee';
import { EmployeeService } from './employee.service';
import { ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';
// Import
rxjs retry operator
import 'rxjs/add/operator/retry';
@Component({
selector: 'my-employee',
templateUrl: 'app/employee/employee.component.html',
styleUrls: ['app/employee/employee.component.css']
})
export class
EmployeeComponent implements OnInit {
employee: IEmployee;
statusMessage: string = 'Loading
data. Please wait...';
retryCount: number = 1;
constructor(private
_employeeService: EmployeeService,
private _activatedRoute: ActivatedRoute,
private _router: Router) { }
ngOnInit() {
let empCode: string = this._activatedRoute.snapshot.params['code'];
this._employeeService.getEmployeeByCode(empCode)
// Chain the
retry operator to retry on error.
.retry()
.subscribe((employeeData) => {
if (employeeData == null) {
this.statusMessage =
'Employee with the specified Employee Code does not exist';
}
else {
this.employee = employeeData;
}
},
(error) => {
this.statusMessage =
'Problem with the service. Please try again after sometime';
console.error(error);
});
}
onBackButtonClick(): void {
this._router.navigate(['/employees']);
}
}
The downside of this approach is that the application keeps on retrying forever. If we start the Web API service, the call succeeds and the observable completes with employee data displayed on the web page.
Now if your requirement is not to retry forever, but only retry for a specific number of times if there is an error then we can use another variation of retry as shown below. Notice in this case we are passing number 3 to the retry opertaor indicating that we only want to retry 3 times. After the 3rd attempt the observable completes with an error.
ngOnInit()
{
let empCode: string = this._activatedRoute.snapshot.params['code'];
this._employeeService.getEmployeeByCode(empCode)
// Retry only 3
times if there is an error
.retry(3)
.subscribe((employeeData) => {
if (employeeData == null) {
this.statusMessage =
'Employee with the specified Employee Code does not exist';
}
else {
this.employee = employeeData;
}
},
(error) => {
this.statusMessage =
'Problem
with the service. Please try again after sometime';
console.error(error);
});
}
The problem with the retry operator is that, it immidiately retries when there is an error. In our case it is a connection issue with the service. Retrying again immediately in our case does not make much sense, as most likely it might fail again. So in situations like this we may want to retry after a short delay, may be after a second or so. This is when we use the retryWhen rxjs operator. retryWhen operator allows us to specify delay in milli-seconds and can be used as shown below. Please donot forget to import retryWhen and delay operators.
import 'rxjs/add/operator/retrywhen';
import 'rxjs/add/operator/delay';
ngOnInit()
{
let empCode: string = this._activatedRoute.snapshot.params['code'];
this._employeeService.getEmployeeByCode(empCode)
// Retry with a
delay of 1000 milliseconds (i.e 1 second)
.retryWhen((err) => err.delay(1000))
.subscribe((employeeData) => {
if (employeeData == null) {
this.statusMessage =
'Employee with the specified Employee Code does not exist';
}
else {
this.employee = employeeData;
}
},
(error) => {
this.statusMessage =
'Problem
with the service. Please try again after sometime';
console.error(error);
});
}
Now if you are wondering can't we use delay opertor with retry operator, the answer is NO, we can't. The delay operator in the following example will not work as expected. As you can see from the browser console, it immediately retries instead of waiting for 5 seconds before a retry attempt.
ngOnInit()
{
let empCode: string = this._activatedRoute.snapshot.params['code'];
this._employeeService.getEmployeeByCode(empCode)
// The delay
operator will not work with retry
.retry().delay(5000)
.subscribe((employeeData) => {
if (employeeData == null) {
this.statusMessage =
'Employee with the specified Employee Code does not exist';
}
else {
this.employee = employeeData;
}
},
(error) => {
this.statusMessage =
'Problem
with the service. Please try again after sometime';
console.error(error);
});
}
If you want to retry every 1000 milli-seconds only for a miximum of 5 times then we can use rxjs scan operator along with the take operator. While retrying we also want to show the retry attempt number to the user on the web page as shown below.
After all the retry attempts are exhausted, the application should stop retrying and display the error message to the user as shown below.
If the connection becomes available between the retry attempts, the application should display employee data.
Here is the complete code.
import { Component, OnInit } from '@angular/core';
import { IEmployee } from './employee';
import { EmployeeService } from './employee.service';
import { ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';
import 'rxjs/add/operator/retrywhen';
import 'rxjs/add/operator/delay';
import 'rxjs/add/operator/scan';
@Component({
selector: 'my-employee',
templateUrl: 'app/employee/employee.component.html',
styleUrls: ['app/employee/employee.component.css']
})
export class
EmployeeComponent implements OnInit {
employee: IEmployee;
statusMessage: string = 'Loading
data. Please wait...';
retryCount: number = 1;
constructor(private
_employeeService: EmployeeService,
private _activatedRoute: ActivatedRoute,
private _router: Router) { }
ngOnInit() {
let empCode: string = this._activatedRoute.snapshot.params['code'];
this._employeeService.getEmployeeByCode(empCode)
// Retry 5
times maximum with a delay of 1 second
// between each
retry attempt
.retryWhen((err) => {
return err.scan((retryCount, val) => {
retryCount += 1;
if (retryCount < 6) {
this.statusMessage = 'Retrying...Attempt #' + retryCount;
return retryCount;
}
else {
throw (err);
}
}, 0).delay(1000)
})
.subscribe((employeeData) => {
if (employeeData == null) {
this.statusMessage =
'Employee
with the specified Employee Code does not exist';
}
else {
this.employee = employeeData;
}
},
(error) => {
this.statusMessage =
'Problem with
the service. Please try again after sometime';
console.error(error);
});
}
onBackButtonClick(): void {
this._router.navigate(['/employees']);
}
}
In our next video, we will discuss how to allow the end user to cancel retry attempts at any point using the unsubscribe method.
Sir please make video crud operation by angular 2 with mvc
ReplyDeletebecause its basic need for any tutorials..
thank you sir
Great .... Thanks For Best Tutorial....
ReplyDelete