(Angular 6) Angular Universal - 不等待内容 API 调用
Posted
技术标签:
【中文标题】(Angular 6) Angular Universal - 不等待内容 API 调用【英文标题】:(Angular 6) Angular Universal - Not waiting on content API call 【发布时间】:2019-02-15 15:10:33 【问题描述】:在将 Angular Universal 用于使用动态内容的页面时,无法使 s-s-r 工作。所有其他页面都正常工作,动态页面返回 html,但不包含动态数据。
方法调用:
ngOnInit()
const div = this.renderer.createElement('div');
const texttest = this.renderer.createText('this works');
this.renderer.appendChild(div, texttest);
this.renderer.appendChild(this.content.nativeElement, div);
this.createLinkForCanonicalURL();
// The HTML never shows, the method works fine.
this._contentfulService.getBlogPosts().then(posts =>
this.blogPosts = _.orderBy(posts, ['sys.createdAt'], ['desc']);
);
服务方式
getBlogPosts(query ? : object): Promise<Entry<any>[]>
return this.cdaClient.getEntries(Object.assign(
content_type: CONFIG.contentTypeIds.blogPosts
,
'fields.private': false
))
.then(res => res.items);
模板:
这永远不会显示在源代码中。
<li class="blog-post" *ngFor="let post of blogPosts">
<h1>post.fields.title</h1>
</li>
已尝试过入门工具包,但它们无法调用相同的方法。还尝试了 render2 注入和解析器服务来测试加载前获取数据。
似乎没有任何效果?
任何帮助将不胜感激!
编辑
这是我的 server.ts 文件
// These are important and needed before anything else
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import enableProdMode from '@angular/core';
import * as express from 'express';
import join from 'path';
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const PORT = process.env.PORT || 8080;
const DIST_FOLDER = join(process.cwd(), 'dist');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const AppServerModuleNgFactory, LAZY_MODULE_MAP =
require('./dist/server/main');
// Express Engine
import ngExpressEngine from '@nguniversal/express-engine';
// Import module map for lazy loading
import provideModuleMap from '@nguniversal/module-map-ngfactory-loader';
app.engine('html', ngExpressEngine(
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// TODO: implement data requests securely
app.get('/api/*', (req, res) =>
res.status(404).send('data requests are not supported');
);
// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));
// All regular routes use the Universal engine
app.get('*', (req, res) =>
res.render('index', req );
);
// Start up the Node server
app.listen(PORT, () =>
console.log(`Node server listening on http://localhost:$PORT`);
);
和我的应用服务器模块
@NgModule(
bootstrap: [AppComponent],
imports: [
BrowserModule.withServerTransition( appId: 'app-root' ),
AppModule,
ModuleMapLoaderModule,
ServerModule,
NoopAnimationsModule,
ServerTransferStateModule, // comment
]
)
export class AppServerModule
【问题讨论】:
首先,当您使用 ng serve 启动应用程序时,它是否有效?您是否尝试过其他页面上的 getBlobPosts 方法,您确定它正在返回数据吗?您可以添加 console.log 以查看 s-s-r 上发生的情况 您使用的是哪个版本的 Angular? 方法100%有效,我用的是angular 6 你能在 stackblitz 上重现这个问题吗? 是的,我确实理解了这个问题,但这通常是由于 s-s-r 期间的服务器端错误引起的(不是谈论 API,而是 nodejs 进程执行 s-s-r)。如果服务器端一切正常,我不确定是什么导致了问题。 【参考方案1】:您需要使用 TransferHttpCacheModule 来等待对 API 的 HTTP 调用,或者使用与 TransferState 一起使用的其他实现,例如 ngx-transfer-http。
等待 3 秒延迟的示例:https://github.com/Angular-RU/angular-universal-starter/blob/master/src/app/transfer-back/transfer-back.component.ts
【讨论】:
如果包含TransferHttpCacheModule
的模块尚未安装在应用程序中,请使用npm install @nguniversal/common@x.x.x --save
安装它(将x.x.x替换为与您的角度应用程序兼容的版本)【参考方案2】:
似乎 Angular Universal 不会等待异步调用来渲染。
我遇到了同样的问题,最后使用issue 中提到的 ZoneMacroTaskWrapper 使它工作。
这是我制作的service。
【讨论】:
【参考方案3】:尝试按如下方式编辑您的代码:
async ngOnInit()
const div = this.renderer.createElement('div');
const texttest = this.renderer.createText('this works');
this.renderer.appendChild(div, texttest);
this.renderer.appendChild(this.content.nativeElement, div);
this.createLinkForCanonicalURL();
const posts = await this._contentfulService.getBlogPosts();
this.blogPosts = _.orderBy(posts, ['sys.createdAt'], ['desc'])
【讨论】:
以上是关于(Angular 6) Angular Universal - 不等待内容 API 调用的主要内容,如果未能解决你的问题,请参考以下文章
Angular 6 中的 AuthHttp(从 Angular2 迁移到 Angular6)
Angular 6 和业力'无法加载“@angular-devkit/build-angular”,它未注册'
Angular JS - 6 - Angular JS 常用指令