Angular4-如何确保导航前完成ngOnDestroy [英] Angular4 - how to ensure ngOnDestroy finishes before navigating away

查看:203
本文介绍了Angular4-如何确保导航前完成ngOnDestroy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象列表.用户可以单击一个,然后加载一个子组件来编辑该组件.

I have a list of objects. The user can click on one, which then loads a child component to edit that component.

我遇到的问题是,当用户返回到列表组件时,子组件必须在ngOnDestroy方法中进行一些清理-这需要调用服务器以对对象进行最终的修补" .有时此处理可能会有点慢.

The problem I have is that when the user goes back to the list component, the child component has to do some cleanup in the ngOnDestroy method - which requires making a call to the server to do a final 'patch' of the object. Sometimes this processing can be a bit slow.

当然,发生的情况是用户返回列表,并且该api调用在ngOnDestroy中的数据库事务完成之前完成,因此用户看到了过时的数据.

Of course what happens is the user arrives back on the list, and that api call completes before the database transaction from the ngOnDestroy completes, and thus the user sees stale data.

  ngOnDestroy(){
    this.destroy$.next();
    this.template.template_items.forEach((item, index) => {
      // mark uncompleted items for deletion
      if (!item.is_completed) {
        this.template.template_items[index]['_destroy'] = true;
      };
    });
    // NOTE 
    // We don't care about result, this is a 'silent' save to remove empty items,
    // but also to ensure the final sorted order is saved to the server
    this._templateService.patchTemplate(this.template).subscribe();
    this._templateService.selectedTemplate = null;
  } 

我了解不建议您进行同步调用,因为它会阻塞UI/整个浏览器,这不是很好.

I understand that doing synchronous calls is not recommended as it blocks the UI/whole browser, which is not great.

我确定有多种方法可以解决此问题,但实际上不知道哪种方法最好(特别是因为Angular不支持同步请求,因此我必须退回到标准的ajax来做到这一点).

I am sure there are multiple ways to solve this but really don't know which is the best (especially since Angular does not support sync requests so I would have to fall back to standard ajax to do that).

我确实想到的一个想法是ngOnDestroy可以将标记"传递给API,然后可以将该对象标记为处理中".当列表组件进行调用时,它可以检查每个对象是否具有该标记,并为处于该状态的任何对象显示刷新陈旧数据"按钮(无论如何,有99%的时间只能是一个项目,用户编辑的最新版本).与仅将异步调用更改为同步调用相比,似乎有点废话解决方案,并且需要大量额外的代码.

One idea I did think of was that the ngOnDestroy could pass a 'marker' to the API, and it could then mark that object as 'processing'. When the list component does its call, it could inspect each object to see if it has that marker and show a 'refresh stale data' button for any object in that state (which 99% of the time would only be a single item anyway, the most recent one the user edited). Seems a bit of a crap workaround and requires a ton of extra code compared to just changing an async call to a sync call.

其他人肯定也遇到过类似的问题,但是除了

Others must have encountered similar issues, but I cannot seem to find any clear examples except this sync one.

编辑

请注意,此子组件已具有CanDeactive防护.它要求用户确认(即放弃更改).因此,如果他们单击以确认,则将执行ngOnDestroy中的此清理代码.但是请注意,这不是用户真正放弃"更改的典型角度形式.基本上,在离开此页面之前,服务器必须对最终数据集进行一些处理.因此,理想情况下,我不希望用户在ngOnDestroy完成之前就离开-如何强制其等待该api调用完成?

Note that this child component already has a CanDeactive guard on it. It asks the user to confirm (ie. discard changes). So if they click to confirm, then this cleanup code in ngOnDestroy is executed. But note this is not a typical angular form where the user is really 'discarding' changes. Essentially before leaving this page the server has to do some processing on the final set of data. So ideally I don't want the user to leave until ngOnDestroy has finished - how can I force it to wait until that api call is done?

我的CanDeactive保护措施的实现与官方文档几乎相同a>对于Hero应用程序,连接到通用对话框服务,该服务会提示用户是希望保留在页面上还是继续前进.在这里:

My CanDeactive guard is implemented almost the same as in the official docs for the Hero app, hooking into a general purpose dialog service that prompts the user whether they wish to stay on the page or proceed away. Here it is:

  canDeactivate(): Observable<boolean> | boolean {
    console.log('deactivating');
    if (this.template.template_items.filter((obj) => { return !obj.is_completed}).length < 2)
      return true;

    // Otherwise ask the user with the dialog service and return its
    // observable which resolves to true or false when the user decides
    return this._dialogService.confirm('You have some empty items. Is it OK if I delete them?');
  }

尽管文档无法明确说明我的情况-即使将清除代码从ngOnDestroy移到对话框的"YES"方法处理程序,它仍然必须调用api,因此YES处理程序仍将完成在API出现之前,我又遇到了同样的问题.

The docs do not make it clear for my situation though - even if I move my cleanup code from ngOnDestroy to a "YES" method handler to the dialog, it STILL has to call the api, so the YES handler would still complete before the API did and I'm back with the same problem.

更新

阅读所有评论后,我猜想解决方案是这样的.更改防护:

After reading all the comments I am guessing the solution is something like this. Change the guard from:

    return this._dialogService.confirm('You have some empty items. 
        Is it OK if I delete them?');

    return this._dialogService.confirm('You have some empty items.
        Is it OK if I delete them?').subscribe(result => {
      ...if yes then call my api and return true...
      ...if no return false...
      });

正如您所说,

推荐答案

有很多方法,它们取决于其他细节,如何设置整个应用程序,数据流和ux-flow,但感觉就像您一样可能想看一下CanDeactivate保护方法,该方法可确保用户在您将Observable<boolean>|Promise<boolean>解析为true之前不能离开路线.

As you said, there are many ways and they depend on other details how your whole app, data-flow and ux-flow is setup but it feels like you might want to take a look at CanDeactivate guard method which ensures user cannot leave route until your Observable<boolean>|Promise<boolean> are resolved to true.

因此,这是一种异步等待方式,直到您的服务确认服务器上的一切已更改为止.

So, its a way for async waiting until your service confirms things are changed on server.

[UPDATE]

这取决于您的用户确认实施方式,但有些方面...

it depends on your user confirmation implementation but something along these lines...

waitForServiceToConfirmWhatever(): Observable<boolean> {
    return yourService.call(); //this should return Observable<boolean> with true emitted when your server work is done
  }

canDeactivate(): Observable<boolean> {

    if(confirm('do you want to leave?') == true)   
      return this.waitForServiceToConfirmWhatever();
    else
      Observable.of(false)
  }

这篇关于Angular4-如何确保导航前完成ngOnDestroy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆