角度传输状态不会阻止重复的 http 调用

2024-05-09

我将 http 请求作为一项服务注入到我的组件中并从那里订阅。由于我在应用程序中引入了具有通用角度的服务器端渲染,因此页面上的结果至少重复两次。

我有一个在单击时调用的方法,该方法对 facebook 的 api 执行 http 请求

getAlbum(albumId: number) {

    this.albumPhotos = this.state.get(ALBUM_PHOTOS_KEY, null as any);

    if (!this.albumPhotos) {
      this.facebookService.getBachadiffAlbumPhotos(albumId).subscribe(res => {
        this.bachataPicsArray = res;
        this.state.set(ALBUM_PHOTOS_KEY, res as any);
      });
    }
  }

我在导入下面声明了 const 变量

const ALBUM_PHOTOS_KEY = makeStateKey('albumPhotos');

而且我还申报了财产

albumNames: any;

我假设我已经完成了所有导入,我有代码画廊组件中的 github https://github.com/Feroli/bachadiff/blob/master/src/app/gallery/gallery.component.ts.


您的做法是正确的,如果您在服务器或浏览器端仅执行一次查询而不是两次,则只需以不同的方式处理您的服务即可。

伪逻辑:

  • 如果服务器 -> 执行 http 请求 -> 在传输状态中设置值
  • 如果浏览器 -> 从传输状态获取值

为此,您可以例如增强您的服务,如下所示:

@Injectable()
export class FacebookEventsService {
    const ALBUM_PHOTOS_KEY: StateKey<number>;

    constructor(@Inject(PLATFORM_ID) private platformId: Object, private http: HttpClient) {
       this.ALBUM_PHOTOS_KEY = makeStateKey('albumPhotos');
    } 

    getBachaDiffFacebookEvents(): Observable<CalendarEvent[]> {
        // Here we check if server or browser side
        if (isPlatformServer(this.platformId)) {
            return this.getServerBachaDiffFacebookEvents();
        } else {
            return this.getBrowserBachaDiffFacebookEvents();
        }
    }

    getServerBachaDiffFacebookEvents(): Observable<CalendarEvent[]> {

           return this.http.get(this.facebookEventsUrl)
             .map(res => {

                  // Here save also result in transfer-state
                  this.transferState.set(ALBUM_PHOTOS_KEY, calendarEvents);

             });
     }


        getBrowserBachaDiffFacebookEvents(): Observable<CalendarEvent[]> {
           return new Observable(observer => {
            observer.next(this.transferState.get(ALBUM_PHOTOS_KEY, null));
          });
     }
}

UPDATE

要使用此逻辑,您还需要:

  1. TransferHttpCacheModule(在 app.module.ts 中初始化)。

TransferHttpCacheModule 安装一个 Http 拦截器,避免 客户端上重复的 HttpClient 请求 当应用程序在服务器端呈现时已经完成。

https://github.com/angular/universal/tree/master/modules/common https://github.com/angular/universal/tree/master/modules/common

  1. ServerTransferStateModule在服务器端和BrowserTransferStateModule在客户端使用 TransferState

https://angular.io/api/platform-b​​rowser/TransferState https://angular.io/api/platform-browser/TransferState

P.S.:请注意,如果您这样做并增强了您的服务器,当然您将不再需要在上面显示的 getAlbum() 方法中设置传输状态中的值

UPDATE 2

如果您想像在您的中那样处理服务器和浏览器端gallery.component.ts,您可以执行以下操作:

getAlbum(albumId: number) {

    if (isPlatformServer(this.platformId)) {

      if (!this.albumPhotos) {
        this.facebookService.getBachadiffAlbumPhotos(albumId).subscribe(res => {
          this.bachataPicsArray = res;
          this.state.set(ALBUM_PHOTOS_KEY, null);
        });
      }
    } else {

      this.albumPhotos = this.state.get(ALBUM_PHOTOS_KEY,null);
    }

  }

UPDATE 3

问题是,你的行动getAlbum永远不会在服务器端被调用。此操作仅在浏览器端、页面呈现后、当用户单击特定操作时使用。因此,在该特定情况下使用转移状态是不正确/不需要的。

此外,不确定您服务中的 Observable 是否已正确订阅。

这里需要更改哪些内容才能使其运行:

gallery.component.ts

getAlbum(albumId: number) {

    this.facebookService.getBachadiffAlbumPhotos(albumId).subscribe(res => {
        this.albumPhotos = res;
    });
  }

facebook-events.service.ts

getBachadiffAlbumPhotos(albumId: number): Observable<Object> {

    this.albumId = albumId;
    this.facebookAlbumPhotosUrl =    `https://graph.facebook.com/v2.11/${this.albumId}/photos?limit=20&fields=images,id,link,height,width&access_token=${this.accessToken}`;

    return    Observable.fromPromise(this.getPromiseBachaDiffAlbumPhotos(albumId));
  }

private getPromiseBachaDiffAlbumPhotos(albumId: number): Promise<{}> {
    return new Promise((resolve, reject) => {
      this.facebookAlbumPhotosUrl = `https://graph.facebook.com/v2.11/${this.albumId}/photos?limit=20&fields=images,id,link,height,width&access_token=${this.accessToken}`;

      let facebookPhotos: FacebookPhoto[] = new Array();
      let facebookPhoto: FacebookPhoto;

      const params: HttpParams = new HttpParams();
      this.http.get(this.facebookAlbumPhotosUrl, {params: params})
        .subscribe(res => {

          let facebookPhotoData = res['data'];

          for (let photo of facebookPhotoData) {

            facebookPhotos.push(
              facebookPhoto = {
                id: photo.id,
                image: photo.images[3].source,
                link: photo.link,
                height: photo.height,
                width: photo.width
              });
          }

          resolve(facebookPhotos);
        }, (error) => {
          reject(error);
        });
    });
  }

UPDATE 4

ngOnInit 在服务器端执行,这意味着我在这里的第一个答案必须在这种情况下使用。

此外,还要注意,在服务器端您无权访问该窗口,因此调用$

With gallery.component.ts你可以做这样的事情来只运行一次http查询,但这并不能解决你所有的问题,我认为它仍然需要进一步的改进。

ngOnInit() {
    if (isPlatformServer(this.platformId)) {
      this.facebookService.getBachadiffFacebookVideos().subscribe(res => {
        this.bachataVidsArray = res;
        this.state.set(VIDEOS_KEY, res as any);
      });


  this.facebookService.getBachadiffFacebookLastClassPictures().subscribe(res => {
        this.bachataPicsArray = res;
        this.state.set(LAST_CLASS_PICTURES_KEY, res as any);
      });

      this.facebookService.getBachadiffAlbumNames().subscribe(res => {
        this.bachataAlbumHeaderNames = res;
        this.state.set(ALBUM_NAMES_KEY, res as any);
      });
    } else {
      $('ul.tabs').tabs();

      this.bachataVidsArray = this.state.get(VIDEOS_KEY, null as any);
      this.bachataPicsArray = this.state.get(LAST_CLASS_PICTURES_KEY, null as any);
      this.bachataAlbumHeaderNames = this.state.get(ALBUM_NAMES_KEY, null as any);
    }
  }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

角度传输状态不会阻止重复的 http 调用 的相关文章

  • mocha.opts 已弃用,如何迁移到 package.json?

    我正在开发一个大型项目 自从上周我更新了摩卡以来 现在我们收到警告 DeprecationWarning 通过 mocha opts 进行的配置已被弃用并且 将从 Mocha 的未来版本中删除 使用 RC 文件或 改为 package js
  • ES6 类文字中的 IIFE

    在 ES5 中我们都可以这样做 myClass prototype myMethod function return function 我可以对 ES6 类文字执行同样的操作吗 不 至少现在还没有 ES6 类仅支持声明方法 因此任何不直接为
  • Angular/ HTML5 到 iOS WKWebView 通信

    我们正在尝试看看发送信号的最佳选择是什么To iOS WKWebView fromAngular 6 HTML5 项目 任何示例都会很棒 我们想要做的是 我们在 Angular 网页上有一个按钮 单击该按钮应该通知 iOS 执行某些操作 我
  • 通过 Javascript 更改 Webkit 属性?

    请帮助我 可能是因为我对 CSS 动画和 Javascript 相当陌生 但我使用的代码应该更改它的属性 当我运行代码时 它会执行代码中的所有其他操作 除了更改所需 div 的 CSS 属性 我已经尝试了所有这四种方法 但似乎都不起作用 它
  • 如何从对象数组中删除所有重复项?

    This is a large array of objects e g let totalArray id rec01dTDP9T4ZtHL4 fields user id 170180717 user name abcdefg even
  • Express JS:请求的资源上不存在“Access-Control-Allow-Origin”标头

    我有一个在服务器上运行的 API 和一个连接到它以检索数据的前端客户端 我对跨域问题做了一些研究并使其发挥作用 但我不确定发生了什么变化 我现在在控制台中收到此错误 XMLHttpRequest 无法加载https api mydomain
  • 如何将查询参数添加到守卫中的路由并将其传递给 Angular 4 中的组件?

    我在我的 Angular 4 应用程序中使用路由保护 如果条件满足并返回 true 我想向路由添加一个查询参数 这是我一直在研究的代码 Injectable export class ViewGuardService implements
  • UpdatePanel 启动脚本未执行

    我正在编写一个在 SharePoint 网站中使用的 ASP NET Web 部件 并尝试使用 UpdatePanel 来呈现查询结果 我想使用 JQuery 插件来修改从异步回发返回的表 但我无法让启动脚本在异步更新上执行 我发现这个帖子
  • 如何获取 Spotify API 的访问令牌?

    我已经研究 Spotify api 和示例源代码几天了 但我仍然不知道如何获取访问令牌来访问用户的播放列表数据 我已经到达了拉起登录窗口 用户登录 然后收到授权码的地步 此时 我尝试做这样的事情 window open https acco
  • JavaScript/jQuery - “$ 未定义 - $function()”错误

    我正在尝试运行 JavaScript jQuery 函数并且Firebug http en wikipedia org wiki Firebug 28software 29得到错误 is not defined function JavaS
  • Jquery 子元素发生变化

    我正在尝试使用 jquery 在子元素 在本例中为 select 更改时触发事件 这是我的 HTML div class row addForm div class col lg 2 col md 2 col sm 3 col xs 6 d
  • 如何使用 Node.js 解析 JSON? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我应该如何使用 Node js 解析 JSON 是否有一些模块可以安全地验证和解析 JSON 你可以简单地使用JSON parse h
  • 如何获取从 Express (Node.js) 中的表单传递的数据

    我想获取使用表单从页面传递的数据 并在重定向的页面中使用该数据 我的客户端有这个表格
  • 如何使用 API 中的数据填充选择的下拉元素 - ReactJS

    我对 React 还很陌生 我正在从 API 获取数据 当我检查控制台日志时可以看到数据 但是我不知道如何使用 map 创建一个新数组 然后选项元素可以使用该数组来显示货币代码 目前它填充下拉列表 但选项元素全部为空 结果显示为 NaN 下
  • redux - 如何存储和更新键/值对

    我正在使用 redux 和 React js 我想存储简单的键 值对 但无法获得正确的减速器语法 在这种情况下 每个键 值对将保持与外部系统的连接 这是正确的做法吗 我刚开始使用 redux 所以这有点神秘 export default s
  • 禁用移动设备上的锚点菜单点击

    我使用嵌套列表作为带有子菜单项的菜单 我曾经这样做过 如果您将鼠标悬停在主菜单项上 子菜单项将通过将显示从无更改为块来出现 我决定让子菜单看起来就像是下拉的 并使用了 CSS 过渡 我遇到的问题是 在第一种方法中 如果您触摸 iPad 上的
  • 如何在react.js中将/n替换为换行符?

    我正在尝试更换每一个 n to a br tag in ReactJS In my note note对象有一个包含多个的字符串 n in it 示例注释 注释 test ntest ntest 我尝试过的ReactJS note note
  • 如何使用 Chart.js 版本 3.2.1 在圆环图中添加文本

    我正在使用 Canvas 在 HTML 中使用 如何使用在圆环图中添加文本 这是我的 javascript 代码和 HTML 代码 我使用了图表js版本3 2 1 所以请给出相同版本 3 的解决方案 var overallStatsCanv
  • 文件和目录条目 API 在 Chrome 中损坏?

    我正在尝试使用文件和目录条目 API 创建一个文件上传器工具 该工具允许我将文件和目录的任意组合放入浏览器窗口中 以供读取和上传 我完全意识到 可以通过使用文件输入元素来实现类似的功能webkitdirectory已启用 但我正在测试一个用
  • 用于替换前 5 个数字的正则表达式,无论它们之间有什么?

    我正在努力实现以下匹配 Input 123 45 6789 123456789 1234 正则表达式尝试输出 d 5 123 45 6789 123456789 1234 d 2 3 123 45 6789 123456789 1234 d

随机推荐

  • win32 内容已更改,但除非移动窗口,否则不会显示更新

    我的 win32 GUI 内容每秒都会更改 但除非手动移动窗口 否则不会显示更新 我尝试每秒弹出一个消息框来触发窗口刷新 它成功了 因此 这证明我的内容确实发生了变化 但窗口没有更新 我希望刷新窗口而不是每次都弹出消息框 有没有这样的窗口功
  • vcproj/vsprops 的可选环境变量

    有没有办法在项目文件 有或没有 vsprops 中进行环境变量替换 如果找不到该变量 则用默认值替换 我还没有找到任何方法来做到这一点 因为一切似乎都会覆盖环境变量 编辑 我需要它为属性工作 而不是为环境变量工作 具体来说 可以使用指定目标
  • Android 如何在按下或聚焦时使 TextView 文本变为粗体

    我的布局中有一个文本视图 我的要求是当我按下或聚焦它时 文本应该是粗体 否则应该使用普通字体 我该如何实施 使用下面的代码 TextView name TextView findViewById R id TextView01 name h
  • Carrierwave 在文件上传时抛出“堆栈级别太深”错误

    我有一个奇怪的问题 不知道如何进一步调试 如果我用 html 表单上传文件 我会得到 SystemStackError stack level too deep 痕迹是 Started POST global accounts 82 for
  • Alsa 带有来自调制解调器的 PCM 接口

    我有一个基于 imx28 CPU 的定制板 CPU 的串行端口连接到调制解调器的 PCM 输出 我必须为调制解调器的 PCM 接口开发一个驱动程序 使其成为 ALSA SoC 的一部分 您能指出内核树 中与我的设置重新组合的一些驱动程序吗
  • 如何从多模块构建中的不同模块引用 SBT 设置

    在带有子模块的多模块构建中server我写了一个自定义任务server build sbt我想在其中提到baseDirectory根项目的 这是任务 lazy val genData taskKey Unit generate files
  • Python正则表达式:如何用不同的值替换出现的每个实例?

    假设我有这个字符串 s blah blah blah 使用Python正则表达式 如何用不同的值替换 blah 的每个实例 例如 我有一个值列表v 1 2 3 你可以使用re sub打回来 http docs python org libr
  • 为什么在嵌套类上调用方法时不调用父类的静态构造函数?

    给出以下代码 为什么在 Main 的第一行之后没有调用 Outer 的静态构造函数 namespace StaticTester class Program static void Main string args Outer Inner
  • 神秘的 getClobVal()

    我有一个表 AKADMIN 其中包含 XMLTYPE 列 其名称为 XML 我想在该列中使用 getClobVal select t xml getClobVal t xml getClobVal t xml getClobVal as c
  • 替换 firebase 键中无效字符的好方法?

    我的用例是保存用户的信息 当我尝试使用用户的电子邮件地址作为密钥将数据保存到 Firebase 时 Firebase 会引发以下错误 错误 密钥无效 电子邮件受保护 cdn cgi l email protection 不能包含 因此 显然
  • firefox 不支持 mediastreamtrack.getsources,如何执行等效操作

    有没有等效的方法来获取连接到 PC 的视频设备列表 除了内置网络摄像头连接之外 我还有一个外部网络摄像头连接 mediastreamtrack getsources 在 Chrome 中工作 但 Firefox 报告 TypeError M
  • 如何在 Java 中获得无代理连接?

    我如何避免经历ProxySelector当与URLConnection或者更确切地说 如何获得保证不受 Java 知道的任何代理的连接 我以为这是什么代理 NO PROXY http docs oracle com javase 8 doc
  • 条件 scalacSettings/settingKey

    我想要我的scalacSettings当我发出自己的命令时要更严格 更多的 linting validate 实现这一目标的最佳方法是什么 新的范围 strict 确实有效 但是当您发出时需要编译项目两次test 所以这不是一个选择 SBT
  • Ansible git clone“权限被拒绝”但直接 git clone 工作

    我在使用 Ansible 时遇到了一个令人不安的问题 我使用当前主机的 ssh 密钥在我的环境中设置 git 克隆 name Add user Public Key copy src Users alexgrs ssh id rsa pub
  • 无法在 Azure Functions 中创建文件

    我有一个在应用服务计划上运行的 Azure 功能 此函数应用程序从 sftp 下载文件并执行一些处理 验证 然后上传到 blob 存储 这是工作代码 我必须进行一些更改 以便我必须保存物理文件 FileStream 而不是 MemorySt
  • 如何在 iOS 中按下后退按钮时创建确认弹出窗口?

    我想在有人按下 iOS 应用程序的 后退 按钮时添加一个弹出窗口 询问用户是否真的想回来 然后 根据用户的响应 我想撤消该操作或继续 我尝试在视图的 viewWillDisappear 函数中添加代码 然后编写正确的委托 但它不起作用 因为
  • 带有移动前端UI框架的流星[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 有人将meteor与移动前端框架集成吗 为了使移动 html5 应用程序看起来 更原生 有许多 CSS 前端框架 例如 流星http
  • 使用文件处理程序时 numpy savetxt 失败

    在Windows 7上 使用最新的numpy 1 13 3和PYTHON 3 5 如果我有一个名为points的数组 其形状为m x 6 dtype为float32 我可以将数组保存到 foo txt 文件中 如下所示 np savetxt
  • 属性错误:模块“flax”没有属性“optim”

    我的代码如下 pip install flax init params TransporterNets init key init img init text init pix params print f Model parameters
  • 角度传输状态不会阻止重复的 http 调用

    我将 http 请求作为一项服务注入到我的组件中并从那里订阅 由于我在应用程序中引入了具有通用角度的服务器端渲染 因此页面上的结果至少重复两次 我有一个在单击时调用的方法 该方法对 facebook 的 api 执行 http 请求 get