Cha*_*n15 6 typescript server-side-rendering angular-universal angular
我已经开始实现角度通用,并能够通过服务器端渲染呈现html的静态部分.我面临的问题是,正在进行API调用,服务器正在呈现html而不等待http调用完成.因此,我的模板依赖于从api调用获得的数据的部分不会在服务器上呈现.
更多信息:
我在节点服务器中使用身份验证服务,只有在用户通过身份验证时才会为索引html提供身份验证,并在响应时设置cookie.
每当我从angular进行API调用时,我也会将cookie作为标头发送,因为依赖服务也会使用令牌验证用户.对于服务器端呈现,由于cookie在服务器级别不可用,我已成功注入请求并为API调用选择cookie.因此,API调用是成功的,但服务器不等待呈现,直到promise解析.
我试过的步骤没有成功:
我已根据此评论中的建议更改了我的区域版本https://github.com/angular/universal-starter/issues/181#issuecomment-250177280
如果需要进一步的信息,请告诉我.
将我引导到一个有角度的通用样板,它可以帮助我.
小智 5
我创建了一个使用muradm代码进行异步 API 调用的服务。
import { Injectable } from '@angular/core';
import { Observable, Observer, Subscription } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AsyncApiCallHelperService {
taskProcessor: MyAsyncTaskProcessor;
constructor() {
this.taskProcessor = new MyAsyncTaskProcessor();
}
doTask<T>(promise: Promise<T>) {
return <Observable<T>> this.taskProcessor.doTask(promise);
}
}
declare const Zone: any;
export abstract class ZoneMacroTaskWrapper<S, R> {
wrap(request: S): Observable<R> {
return new Observable((observer: Observer<R>) => {
let task;
let scheduled = false;
let sub: Subscription|null = null;
let savedResult: any = null;
let savedError: any = null;
// tslint:disable-next-line:no-shadowed-variable
const scheduleTask = (_task: any) => {
task = _task;
scheduled = true;
const delegate = this.delegate(request);
sub = delegate.subscribe(
res => savedResult = res,
err => {
if (!scheduled) {
throw new Error(
'An http observable was completed twice. This shouldn\'t happen, please file a bug.');
}
savedError = err;
scheduled = false;
task.invoke();
},
() => {
if (!scheduled) {
throw new Error(
'An http observable was completed twice. This shouldn\'t happen, please file a bug.');
}
scheduled = false;
task.invoke();
});
};
// tslint:disable-next-line:no-shadowed-variable
const cancelTask = (_task: any) => {
if (!scheduled) {
return;
}
scheduled = false;
if (sub) {
sub.unsubscribe();
sub = null;
}
};
const onComplete = () => {
if (savedError !== null) {
observer.error(savedError);
} else {
observer.next(savedResult);
observer.complete();
}
};
// MockBackend for Http is synchronous, which means that if scheduleTask is by
// scheduleMacroTask, the request will hit MockBackend and the response will be
// sent, causing task.invoke() to be called.
const _task = Zone.current.scheduleMacroTask(
'ZoneMacroTaskWrapper.subscribe', onComplete, {}, () => null, cancelTask);
scheduleTask(_task);
return () => {
if (scheduled && task) {
task.zone.cancelTask(task);
scheduled = false;
}
if (sub) {
sub.unsubscribe();
sub = null;
}
};
});
}
protected abstract delegate(request: S): Observable<R>;
}
export class MyAsyncTaskProcessor extends
ZoneMacroTaskWrapper<Promise<any>, any> {
constructor() { super(); }
// your public task invocation method signature
doTask(request: Promise<any>): Observable<any> {
// call via ZoneMacroTaskWrapper
return this.wrap(request);
}
// delegated raw implementation that will be called by ZoneMacroTaskWrapper
protected delegate(request: Promise<any>): Observable<any> {
return new Observable<any>((observer: Observer<any>) => {
// calling observer.next / complete / error
request
.then(result => {
observer.next(result);
observer.complete();
}).catch(error => observer.error(error));
});
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助别人。
最后,解决方案是将外部 API 异步调用安排为宏任务。这个问题的解释很有帮助。为外部 API 异步调用实现ZoneMacroTaskWrapper类似的帮助器包装类,渲染进程会等待外部承诺。
目前,ZoneMacroTaskWrapper尚未公开 API。但有一个承诺提供文件。
为了便于说明,猴子输入示例:
export class MyAsyncTaskProcessor extends
ZoneMacroTaskWrapper<MyRequest, MyResult> {
constructor() { super(); }
// your public task invocation method signature
doTask(request: MyRequest): Observable<MyResult> {
// call via ZoneMacroTaskWrapper
return this.wrap(request);
}
// delegated raw implementation that will be called by ZoneMacroTaskWrapper
protected delegate(request: MyRequest): Observable<MyResult> {
return new Observable<MyResult>((observer: Observer<MyResult>) => {
// calling observer.next / complete / error
new Promise((resolve, error) => {
// do something async
}).then(result => {
observer.next(result);
observer.complete();
}).catch(error => observer.error(error));
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1530 次 |
| 最近记录: |