Error Handling in a POST Request in Angular - html

I am following the guide at official Angular documentation at https://angular.io/guide/http.
The handleError function in the post request has 2 arguments and it's giving me an error of 'expected 1 argument but got 2'.
The code for error handling is:
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something bad happened; please try again later.');
};
The code for the post request is:
/** POST: add a new hero to the database */
addHero (hero: Hero): Observable<Hero> {
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions)
.pipe(
catchError(this.handleError('addHero', hero))
);
}
Does the function need no argument in any case?
I think it's trying to call the function again with the argument of hero in case of error. Is that so?
Thank you.

The angular guide is actually wrong/confusing on this, or at least, they did not show the right examples. When you do something like this:
catchError(this.handleError('addHero', hero))
The handleError should accept two parameters, and also return a function which accepts one parameter. So something like this:
handleError<T>(action: string, object: T): (e: HttpErrorResponse) => Observable<never> {
return (e: HttpErrorResponse) => {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError(
`Something bad happened while performing action: ${action}, on object ${object}`
);
};
}
If you want the handleError be like the one you have:
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError(
'Something bad happened; please try again later.'
);
};
You should change the way you pass this into the catchError:
catchError((error: HttpErrorResponse) => this.handleError(error));
If you are not accessing the this context from the handleError you can do the following:
catchError(this.handleError)
In this part of the guide, it's explained better. It's just that the examples in the POST and PUT sections are missing the correct implementation of the handleError method

Related

Laravel 8 API Unauthorized Handler Not Showing

I would like to add a custom response when an endpoint is being accessed without access token. I added this line of code into my Handler.php
public function render($request, Exception $exception)
{
if ($exception instanceof AuthorizationException) {
return response()->json([
'message' => 'Unauthorized'
],401);
}
return parent::render($request, $exception);
}
Instead of getting the json response, I got a blank response with 500 error code on postman. What am I doing wrong?
The Response:
I figured it out by making sure that the server's response is in JSON. So I made a middleware file called ForceJsonResponse.php. Here is the code:
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
Registered it in Kernel.php on $middleware as
\App\Http\Middleware\ForceJsonResponse::class,
And in $routeMiddleware as
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,

How to print out Apify requestQueue.getInfo() at run time?

The docs on requestQueue.getInfo().
Code
function printRequestQueue(requestQueue){
let { totalRequestCount, handledRequestCount, pendingRequestCount } =
requestQueue.getInfo()
.then(()=> {
console.log('\nRequest Queue:\n total:', this);
console.log('\nRequest Queue:\n total:', totalRequestCount);
console.log(' handled:', handledRequestCount, '\n pending:', pendingRequestCount);
})
.catch( (error) => console.log(error));
}
When run in the runtime environment Apify.main(async () => { ... }, it returns undefined:
Request Queue:
total: undefined
handled: undefined
pending: undefined
You don't seem to be returning the contents of the response back from the operation promise and so the variables are indeed uninitialized at the time of logging them. Operation itself should be returning this result and you can confirm so by logging the result of the promise - e.g. .then(response) => {console.log(response)}:
https://sdk.apify.com/docs/typedefs/request-queue-info
Thanks to Vasek. I post below 2 solutions:
Solution 1
async function printRequestQueue (requestQueue){
var { totalRequestCount, handledRequestCount, pendingRequestCount } = await
requestQueue.getInfo();
console.log(`Request Queue info:` );
console.log(' - handled :', handledRequestCount);
console.log(' - pending :', pendingRequestCount);
console.log(' - total:' , totalRequestCount);
}
Solution 2
function printRequestQueue (requestQueue){
requestQueue.getInfo().then((response)=> {
console.log('total:', response.totalRequestCount);
console.log('handled:', response.handledRequestCount, '\n pending:',
response.pendingRequestCount);
console.log('\nFull response:\n', response); })
.catch( (error) => console.log(error));
}
One may read full explanation in here.

Issue Regarding BehaviorSubject Observable

I am trying to Sync the data from REST API to my UI. but when i fetch the record from Rest API and transforms it,it gives an error of undefined:-
I am attaching my code:-
private datalist: Data[];
private dataUpdated = new Subject<Data[]>();
constructor(private http:HttpClient) {
}
getData()
{
this.http.get<{datalist:any}>("http://myserever/posts")
.pipe(map((dummydata)=>{
return dummydata.datalist.map(da=>{
return {
Status:da.status
};
})
}))
.subscribe(data=>{
this.datalist=data
console.log("The data is",data);
this.dataUpdated.next([...this.datalist]);
})
}
Actual Results:-
On pipe Operator it is giving me undefined Error, Here is my Error stack:-
ERROR TypeError: Cannot read property 'map' of undefined
at MapSubscriber.eval [as project] (get-dummy-data.service.ts:25)
at MapSubscriber._next (map.js:79)
at MapSubscriber.Subscriber.next (Subscriber.js:95)
at MapSubscriber._next (map.js:85)
at MapSubscriber.Subscriber.next (Subscriber.js:95)
at FilterSubscriber._next (filter.js:90)
at FilterSubscriber.Subscriber.next (Subscriber.js:95)
at MergeMapSubscriber.notifyNext (mergeMap.js:151)
at InnerSubscriber._next (InnerSubscriber.js:25)
at InnerSubscriber.Subscriber.next (Subscriber.js:95)
How i can solve the above probelm
Thank you
First of all you are not using a BehaviorSubject but a Subject (the difference matter, the behavior subject has a value at initialization, the Subject hasn't).
This post resume the difference What is the difference between Subject and BehaviorSubject?
It will depends of your needs to switch for a real behavior subject.
The error, "Cannot read property 'map' of undefined" could be due to your dummydata result that does not contains a datalist property (check casing, spelling ?)
The first map will just take the result of the request (dummydata), then the second will try to iterate on dummydata.datalist property (is it an array, an object?).
So you could check first if the dummydata.datalist property is not undefined, and that it is an iterable thing.
You could modify your code to be like this:
getData(){
this.http.get<{datalist:any}>("http://myserever/posts").pipe(
map(dummydata => dummydata.datalist.map(da => {
return {
Status: da.status
}
})),
// Catch it here
catchError(error => of([{Status: 'Fail'}]))
).subscribe(
data => {
this.datalist=data
console.log("The data is",data);
this.dataUpdated.next([...this.datalist]);
},
// Or catch it here
err => {
//Do your error handling
},
() => // Do something in any case
)
}
Hope this can help you.

Node.js ERROR: (node:9748) UnhandledPromiseRejectionWarning: Unhandled promise rejection

I'm trying to get a json from "nightmare" in Node.js and then use JSON.parse(), but I'm getting the following error:
(node:9748) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: Unexpected token ☻ in JSON at position 18509
My code:
var nightmare = Nightmare()
.goto('URL')
.wait(10000) // Need wait some time
.evaluate(() => {
return document.body.innerText;
})
.end()
.then((body) => {
var data;
try {
data = JSON.parse(body);
} catch(e) {
console.log(e);
}
callback(null, data);
});
You can check if the JSON is valid or not simply using the JSON.parse function as you are using.
function validJSON(str) {
try {
// try to parse the JSON
JSON.parse(str);
} catch (e) {
// if not a json
return false;
}
// if it's valid json
return true;
}
It'll check if the string is valid json or not. Now, you can use it with your nightmareJS.
const nightmare = Nightmare()
.goto("URL")
.wait(10000) // Need wait some time
.evaluate(() => {
return document.body.innerText;
})
.end()
.then(body => {
// if it's a valid json, send it,
// otherwise send it as a body object
const data = validJSON(body) ? body : { body };
callback(null, data);
});
Now, the error is showing because you said to catch(e) and console.log(e) the error. Thus it's simply obeying your command.
Since the emoji itself is not a valid json, you have to either make a json from it, or parse it if it was a json string.
A valid json object might look like this,
{emoji: "☻"}
You see how it's all quoted?

ASP.NET MVC client valitation on ui-dialog?

Razor:
#Html.TextBoxFor(kod => kod.Name)
#Html.ValidationMessage("Name","Client Error Message")
Controller:
[HttpPost]
public JsonResult JsonAddCustomer(Customers customer, string returnUrl)
{
if (customer.Name.Trim().Length == 0)
{
ModelState.AddModelError("Name", "Server Error Message");
}
//Eğer hata yoksa veri tabanına kayıt yapılıyor.
if (ModelState.IsValid)
{
try
{
CusOpp.InsertCustomer(customer);
return Json(new { success = true, redirect = returnUrl });
}
catch (Exception e)
{
ModelState.AddModelError("", "Error");
}
}
return Json(new { errors = GetErrorsFromModelState() });
}
I want to write validation error message. I did this like above, but #Html.ValidationMessage("Name","Client Error Message") does not work. In fact, I was already expecting it.
I want to show like this statement's result: #Html.ValidationMessageFor(m => m.name) ,but I cant use this, because I used entity-data-model.
Should I add [Required] statement to data-model classes or any way that I do this. Sorry for bad explanation.
Thanks.
You should return PartialViews instead of JSON in this case. Only in the case of success you could return JSON:
[HttpPost]
public ActionResult JsonAddCustomer(Customers customer, string returnUrl)
{
// Warning: the following line is something horrible =>
// please decorate your view model with data annotations or use
// FluentValidation.NET to validate it.
// Never write such code in a controller action.
if (customer.Name.Trim().Length == 0)
{
ModelState.AddModelError("Name", "Server Error Message");
}
//Eğer hata yoksa veri tabanına kayıt yapılıyor.
if (ModelState.IsValid)
{
try
{
CusOpp.InsertCustomer(customer);
return Json(new { success = true, redirect = returnUrl });
}
catch (Exception e)
{
ModelState.AddModelError("", "Error");
}
}
return PartialView(customer);
}
Now inside the success callback of your AJAX request you can test whether the POST action succeeded or not:
success: function(result) {
if (result.redirect) {
// we are in the success case => redirect
window.location.href = result.redirect;
} else {
// a partial view with the errors was returned => we must refresh the DOM
$('#some_container').html(result);
// TODO: if you are using unobtrusive client side validation here's
// the place to call the $.validator.unobtrusive.parse("form"); method in order
// to register the unobtrusive validators on the newly added contents
}
}
Here's a similar post that you might also read through.
Your Idea with the Required annotation on the model is a good approach. You can set a Error Message on the Required annotation.
[Required(ErrorMessage = "Please enter a name")]
and remove your if in your action..this:
if (customer.Name.Trim().Length == 0)
{
ModelState.AddModelError("Name", "Server Error Message");
}
the ModelState.IsValid will do the job for you on the client and server side.
And use your #Html.ValidationMessageFor(m => m.name) in your view