Angular 2 Webworkers Http Uncaught (in promise): not implemented - javascript

I've been stuck on an error that I'm not completely sure how to solve.
My application is made in Angular2 and runs completely in a webworker largely based on this tutorial http://www.syntaxsuccess.com/viewarticle/web-workers-in-angular-2.0
My first feature was an implementation of socket.io which is working perfectly(also with observables etc..) but now I want to use the Http service of Angular2 and I get the following error:
My code of the service is like this and the error arrises when I call validateAccessToken (I have to add the .js on my imports otherwise I get a 404 on the files within the webworker):
import { Injectable } from '#angular/core';
import { Http, Headers, RequestOptions, Response } from "#angular/http";
import { environment } from "../../../environments/environment.js";
import { Observable } from "rxjs/Observable.js";
import 'rxjs/add/operator/toPromise.js';
import 'rxjs/add/operator/map.js';
#Injectable()
export class AuthService {
headers: Headers;
options: RequestOptions;
url: string;
constructor(private http:Http) {
this.url = environment.authServerUrl;
}
validateAccessToken(token) {
return this.http.get(this.url)
.map(this.extractData)
.catch(this.handleError);
};
extractData(response: Response) {...}
handleError(error: any) {...}
}
I know the question is quite vague but with the information I get from the error it's not really clear what's going wrong for me.

The CookieXSRFStrategy is default enabled by Angular2 and used by http.
The webworker does not have DOM access to get the cookie to insert in the http headers. And thus throws the error Uncaught not implemented.
You should implement your own CookieXSRFStrategy strategy which at least does not throw this error ;)

Related

Is it safe to set auth 'Cookie' inside interceptor manually?

In my angular application I have interceptor class like that:
import { Injectable, Inject, Optional, PLATFORM_ID } from '#angular/core';
import {
HttpInterceptor,
HttpHandler,
HttpRequest,
} from '#angular/common/http';
import { REQUEST } from '#nguniversal/express-engine/tokens';
import { isPlatformServer } from '#angular/common';
#Injectable()
export class UniversalInterceptor implements HttpInterceptor {
constructor(
#Inject(PLATFORM_ID) private platformId,
#Optional() #Inject(REQUEST) private request
) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
if (isPlatformServer(this.platformId)) {
req = req.clone({ headers: req.headers.set('Cookie', this.request.headers.cookie) });
}
return next.handle(req);
}
}
I am using Angular Universal server side rendering, so I take token from server and manually set in every API call which will be called by server. Everything works fine, but is it safe? I set token cookie manually inside every API request's header, maybe that's somehow risky?
I mayb be wrong, but I think it only matters if you send cookies to an API that you don't own, in which case you might be sending sensitive information to a 3rd party.
If you don't own the API, you could try parsing the cookies string (this.request.headers.cookie) and only pass the ones that the API need

asp.net Core Angular4 angular/common/http not found

My question sounds similar to Cannot find the '#angular/common/http' module and Error loading #angular/common/http - angular 2 but the problem is a bit different:
I am using Angular 4.3.5 and I am trying to read data from a Web API. (This API puts out JSON data and is using SignalR and .net Core).
I have followed several tutorials and came up with this code for the class that will actually contact the service:
import 'rxjs/add/operator/map';
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { Configuration } from './Configuration.js';
#Injectable()
export class DataService {
private actionUrl: string;
constructor(private http: HttpClient, private configuration: Configuration) {
this.actionUrl = configuration.serviceUrl;
}
//public getAll<T>(): Observable<T> {
// return this.http.get<T>(this.actionUrl);
//}
public getSingle<T>(id: number): Observable<T> {
return this.http.get<T>(this.actionUrl + id);
}
}
#Injectable()
export class CustomInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!req.headers.has('Content-Type')) {
req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
}
req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
console.log(JSON.stringify(req.headers));
return next.handle(req);
}
}
Now, building this project (I am using Visual Studio 2017 Enterprise) and running a gulp task to transpile the .ts to .js works just fine, so do all the intellisense-tooltips - the IDE does recognize the existance of those things.
But if I open it up in a browser (doesnt matter if firefox, edge or chrome) I get the following error:
zone.js:958 GET http://localhost:3966/libs/#angular/common/bundles/common.umd.js/http 404 (Not Found)
If I edit the transpiled javascript file by hand and write common-http.umd.js there, the file is found. (This is the reason why at the top I import Configuration.js instead of Configuration - it doesnt seem to want to automatically resolve the suffix, like in some tutorials).
I hope I am not too vague, since this is my first Time asking something publically. Also I was not able to find an answer in the given questions.
Well, I found a solution, for anybody who is curious why this and similar problems exist:
I had to edit my systemjs file and add this line:
'#angular/common/http': 'npm:#angular/common/bundles/common-http.umd.js',
and it works!

Angular 2. Error: Loading chunk failed

Using angular 2 with lazy loaded modules, I can receive(for example) 401 HTTP code from server
bootstrap 0b40fee…:101 GET http://localhost:8082/2.chunk.js
Error: Loading chunk 2 failed.
at HTMLScriptElement.onScriptComplete (bootstrap 0b40fee…:91)
at HTMLScriptElement.wrapFn (zone.js:1032)
at ZoneDelegate.invokeTask (zone.js:414)
at Object.onInvokeTask (core.es5.js:4119)
at ZoneDelegate.invokeTask (zone.js:413)
at Zone.runTask (zone.js:181)
at HTMLScriptElement.ZoneTask.invoke (zone.js:476)
How to handle this error?
Check my answer for details
Workaround to bypass this chunk fails error => Programmatically force app to reload if chunks failed error occurs using global error handler.
import { ErrorHandler } from '#angular/core';
#Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error: any): void {
const chunkFailedMessage = /Loading chunk [\d]+ failed/;
if (chunkFailedMessage.test(err.message)) {
window.location.reload();
}
}
}
Provide it in our root module to change default behavior in our app, so instead of using default ErrorHandler class we are using our custom GlobalErrorHandler class.
#NgModule({
providers: [{provide: ErrorHandler, useClass: GlobalErrorHandler}]
})
I was having the same problem so I investigated. I found the solution. This happened to me when I redeployed to another server and the chunk had a [hash].
You can catch the error either in a catch all like this:
ngOnInit() {
if (!this.previousRouterErrorHandler) {
this.previousRouterErrorHandler = this.router.errorHandler;
let that = this;
this.router.errorHandler = function (err: any) {
// Handle here. err.message == "Loading chunk chunk-name failed."
return that.previousRouterErrorHandler.apply(that.previousRouterErrorHandler, arguments);
};
}
}
Or directly at the link which navigated
click() {
this.router.navigate(['/lazy-route'])
.catch(err => {
// Handle here
});
}
Here is my solution for this. I inject this service as a singleton in my app / core module.
It waits for instances of NavigationError from the router, checks if they are ChunkLoadError's and then does a redirect to the place the user wanted to go to anyway.
// Angular
import { Injectable, OnDestroy } from '#angular/core';
import { Router, NavigationError } from '#angular/router';
// Rxjs
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
#Injectable()
export class ChunkErrorHandler implements OnDestroy {
private subscription: Subscription;
constructor(router: Router) {
this.subscription = router.events
.pipe(filter(event => event instanceof NavigationError))
.subscribe(event => {
this.handleRouterErrors(event as NavigationError);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
private handleRouterErrors(event: NavigationError) {
if (event.error.name === 'ChunkLoadError') {
window.location.href = `${window.location.origin}${event.url}`;
}
}
}
It happen when when deploy new code.The manifest.js which holds the files and hashes doesn't update without refreshing and when it loads a chunk it obviously uses the old hash from manifest.js.
So while catching error we can do force reload with given url :-
click() {
this.router.navigate(['/lazy-route'])
.catch(err => {
// Handle here
// reload with given route
// window.location.pathname('/lazy-route');
// OR
// reset existing route(containing query params) with given route and force reload
window.history.pushState({}, document.title, '/lazy-route' );
window.location.reload();
});
}
chunk related errors can be raised by any environment or routing related issues making them hard to debunk.
In my case, the amount of data moving in my PWA was too much to handle by the angular router. It was flooding the headers of the js chunks getters and therefore raising bad_request errors.
I suggest you to check out those network calls (getters of chunks.js like http://localhost:xxxx/158.js) for anything unusual in headers and refactor sketchy stuff in your current dev environment, since it's a real black hole time to investigate the source of the error by yourself.
Hope that'll help
check out Catch Storage, i guess service worker save some thing in catch storage
console.log(Object.entries(error));
this help me to understand what's inside the error is
rejection,
promise,
zone,
task
and below is my solution:
handleError(error) {
switch (error?.rejection?.name) {
case 'ChunkLoadError':
window.location.href = window.location.href;
break;
default:
break;
}
}
In my case, I was putting my files in an S3 bucket. I kept getting this error because it was calling the wrong filenames all together and returning an html error response.
At some point I let the IT team know what was happening. They were like, let's invalidate the cache on CloudFront... What?! Yeah! Let's do that...
Moral of the story, if you've been searching the web for answers to this error and can't find any, check with the IT team or any place that the index.html file might be getting cached.
this probably means unhandled exception. you have to handle error responses (4xx, 5xx status codes) from server in whatever way you want: show error message somewhere, redirect to some page, do anything but not leave it unhandled.
for example:
return this.http.get(requestDetails)
.map(res => res.json())
.catch(err => {
console.log('server error:', err)
Observable.throw(err);
});

Http get request in Angular 2

I am trying to retrieve data from the Statbureau inflation api- https://www.statbureau.org/en/inflation-api using Angular 2. I am starting off just testing out my api and making sure it outputs a success message in the console. It appears that the api I'm using is JSONP, because of the JSON address that I'm using http://www.statbureau.org/calculate-inflation-price-jsonp?jsoncallback=? On the website they provide a JS fiddle that makes a succesful call to the api using jquery. When I try to make the same call in Angular 2 I get the following errors:
TypeScript error: C:/Users/Rennie/projects/inflator/app/pages/home/home.ts(22,13): Error TS
2322: Type 'Observable<any>' is not assignable to type 'HomePage'.
Property 'jsonp' is missing in type 'Observable<any>'.
TypeScript error: C:/Users/Rennie/projects/inflator/app/pages/home/home.ts(22,13): Error TS
2409: Return type of constructor signature must be assignable to the instance type of the c
Here is my code
import {Component} from '#angular/core';
import {NavController} from 'ionic-angular';
import {Jsonp, URLSearchParams } from '#angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
#Component({
templateUrl: 'build/pages/home/home.html'
})
export class HomePage {
constructor(private jsonp: Jsonp) {
this.jsonp=jsonp;
let cpiUrl = "https://www.statbureau.org/calculate-inflation-price-jsonp?jsoncallback"
let params = new URLSearchParams();
params.set('country', 'united-states');
params.set('amount', '102');
params.set('start', '1968/1/1');
params.set('finish', '2016/1/1');
// TODO: Add error handling
return this.jsonp
.get(cpiUrl, { search: params }).map(function(response){ return response.json(); })
}
}
My code differs from the call in the jsfiddle because I hard coded the api parameters just to quickly see a result.
1) A constructor typically (always?) does not have a return statement. Removing the return statment should handle type 'Observable<any>' is not assignable to type 'HomePage'.
2) There does not seem to be a method get on the Jsonp class in Angular 2 check the docs.
3) An observable sequence/pipeline will not be executed until subscription (they are lazy), so even if that code did compile the request would not be executed.
4) I think you should take a look at this similiar question.
Good luck.

Multipart file upload and ng serve: Angular 2

I am working on the front end of a file upload service. I am currently ignoring the service path with respect to the backend. I have run into a strange problem. I have a few generated components that sit within the app component. When I end the serve from console and do ng serve again, it errors out. It says:
The only way I have found to get rid of this is to erase my uploader service injection, save the file, then re-insert the injection. This is how it is supposed to look:
The only way to get ng serve to work is to by erasing the line private service: UploaderService
Any idea why this is happening? Am I missing something with my injection? My UploaderService is marked as Injectable() and the components that use it are under Directives.
Update:
What I found out is that it is unrelated to the UploaderService. I have a component that does not inject the UploaderService. I fix it the same way I fix the other components that inject the UploaderService. By deleting the parameters of the constructor, saving, and then putting the parameters back. Then it will serve
Update2:
The generated componenet, upload.component.t, has a spec file that is generated with it, upload.component.spec.ts
It has a error that asks for parameters like so:
My UploadComponent constructor has a parameter in it, where i inject the UploaderService. In the spec.ts file, a new UploadCompent is created, but does not contain any arguments. I am guessing this is where I am going wrong. How do I work around this?
Here is my UploaderService:
import { Injectable } from '#angular/core';
import {Http, Response, HTTP_PROVIDERS, Headers, HTTP_BINDINGS, RequestOptions} from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { ItemEntryComponent } from './item-entry';
import { Query } from './Query';
#Injectable()
export class UploaderService {
public URL: string;
private query: Query;
public filesSelected: Array<ItemEntryComponent> = [];
progress$: any;
progress: any;
progressObserver: any;
//CONSTRUCTOR
constructor(private http: Http) {
//***SET URL***
this.URL = 'http://localhost:7547/api/picker';
//Create Query for url
this.query = new Query(this.URL);
//Create progress attribute
this.progress$ = Observable.create(observer => {
this.progressObserver = observer
}).share();
}
}
Problem solved!
I had not realized the generated files included a spec testing file, in my example it was upload.component.spec.ts. Getting rid of those files gets rid of the errors that ask for parameters to be filled in inside the test files and now ng serve works.

Categories