intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (req.method === 'JSONP') { returnthis.jsonp.handle(req as HttpRequest<never>); } // Fall through for normal HTTP requests. return next.handle(req); } }
returnnew Observable<HttpEvent<any>>((observer: Observer<HttpEvent<any>>) => { // let nextRequestId: number = 0; // private nextCallback(): string { return `ng_jsonp_callback_${nextRequestId++}`; } const callback = this.nextCallback(); // 生成唯一的callback名称 // callback=JSONP_CALLBACK 转换为 callback=ng_jsonp_callback_0 const url = req.urlWithParams.replace(/=JSONP_CALLBACK(&|$)/, `=${callback}$1`); // 创建script元素并设定请求的URL地址 const node = this.document.createElement('script'); node.src = url; // The response object, if one has been received, or null otherwise. let body: any|null = null; // Whether the response callback has been called. let finished: boolean = false; // Whether the request has been cancelled (and thus any other callbacks) // should be ignored. let cancelled: boolean = false; // 设置响应的回调函数,浏览器环境则是window对象 this.callbackMap[callback] = (data?: any) => { // Data has been received from the JSONP script. Firstly, delete this callback. deletethis.callbackMap[callback]; // Next, make sure the request wasn't cancelled in the meantime. if (cancelled) { return; } // Set state to indicate data was received. body = data; finished = true; }; }
const onLoad = (event: Event) => { // Do nothing if the request has been cancelled. if (cancelled) { return; }
// Cleanup the page. cleanup();
// 请求失败构造响应对象 if (!finished) { // It hasn't, something went wrong with the request. Return an error via // the Observable error path. All JSONP errors have status 0. observer.error(new HttpErrorResponse({ url, status: 0, statusText: 'JSONP Error', error: newError(JSONP_ERR_NO_CALLBACK), })); return; }
return() => { cancelled = true; // Remove the event listeners so they won't run if the events later fire. node.removeEventListener('load', onLoad); node.removeEventListener('error', onError); // And finally, clean up the page. cleanup(); };