【问题标题】:Does Async process complete as expected even when component is destroyed即使组件被销毁,异步过程是否按预期完成
【发布时间】:2017-03-21 11:32:19
【问题描述】:

我有一个弹出模式,当用户点击模式中的提交时,它会进入我的数据库并在那里保存一些数据。之后模态框关闭。 但是,由于它是一个模式,用户可以通过 ESC 按钮将其关闭。所以我想确保即使用户按下了 ESC,异步仍然可以完成而不会在中间被切断。

例如。

// from my modal component
onSubmit() {
    this.databaseService.saveToDatabase(data)
        .first()
        .subscribe(result => {
            console.log('complete')
            closeModal();
        }, error => {
            console.log(error)
        })
}

ngOnDestroy() {
    console.log('modal Desstroyed')
}

对于上面的例子,如果我一点击提交就按 esc,我会从控制台看到

modal Destroyed

complete

这表明我的异步调用按预期完成,这很好。不过我觉得很奇怪.....为什么 Angular 2 在异步过程完成之前不挂在组件上。 即使组件已被销毁,我的 onSubmit 函数如何完成(假设这是调用 ngOnDestry() 时发生的情况)。在另一种语言如 Swift 中,视图控制器不会被销毁,除非所有过程都完成(除非您指定它无论如何都被销毁)

另一个我没有测试过的例子......如果异步调用长得多,如下所示。如果我在按下提交按钮后立即关闭模式,我是否仍会达到“第二阶段完成”

// from my modal component
onSubmit() {
    this.databaseService.saveToDatabase(data)
        .first()
        .subscribe(result => {
            console.log('complete 1st stage')
            this.databaseService.saveToDatabase(reult)
                .first()
                .subscribe(result => {
                    console.log('2nd stage complete')
                    closeModal();
                })
        })
}

【问题讨论】:

  • onSubmit 立即完成,远在请求完成之前。正如您定义的那样,它是一个即发即忘功能。无论您是否关闭模式,都会发生这种情况。在提交时通过一个闭包来订阅。了解闭包,了解词法作用域,了解 JavaScript。如果您不了解 JavaScript,就无法了解 TypeScript。期间。

标签: javascript angular typescript closures lexical-scope


【解决方案1】:

我不会谈论 JS 的异步性,因为它已经在 Stack Overflow 和许多教程网站等方面进行了介绍。我只会谈论 Observables 和订阅管理。

首先要知道的是“视情况而定”。这取决于您的 Observable 的创建方式以及您管理订阅的方式。

当您使用Observable.create 创建 Observable 时,您可以定义取消订阅时要执行的操作。在此示例中,当您取消订阅时,间隔将停止:

let foo = Observable.create((observer)=>{
  // this is called when an observer subscribe to this Observable
  let interval = setInterval(()=>{
    observer.next("foo");
  });
  // returns what to do on unsubscribe...
  return ()=>{
    clearInterval(interval);
  }
});
let sub = foo.subscribe(data=>console.log(data));
window.setTimeout(()=>sub.unsubscribe(),1000); // passed 1000ms, unsubscribe and cancel the interval...

比如whit angular的Http服务,一个http请求在你退订的时候就被取消了。

虽然您没有取消订阅您的 Observable 并且它没有取消订阅 complete,但它仍在运行,无论组件是否被销毁。

请注意,avoid multiple subscriptions 是一个很好的做法,因为当您强制管理订阅时,您不会从使用 RxJS 中获得好处。因此,最好使用可用的运算符来控制事件的流程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 2012-05-25
    相关资源
    最近更新 更多