为什么我需要键入此命令两次才能在 Typescript、Ionic 2 中工作?



我已经搜索了 2 个小时的问题,我的回调函数不会关闭 Ionic 2 中的加载控制器。

我有一个函数,hideLoad():

hideLoading()
{
this.loader.dismiss();
}

在成功函数中称为

connectionSuccess = () =>
{
this.hideLoading();
var toast = Toast.create({
message: '...',
duration: 3000});
this.nav.present(toast);
}

由于某种原因它不起作用..但我刚刚发现它有效——如果我在两者之间放一个 alert();或者如果我将代码更改为以下内容:

connectionSuccess = () =>
{
this.hideLoading();
this.loader.dismiss();
[...] 
}

是一些与时间相关的错误吗?alert() 在两者之间或第二个隐藏指令的时间似乎可以修复它。在关闭之前,我在控制台日志中检查了this.loader的内容,这是完全正确的。

如果我删除上述两个说明之一,它不起作用。它需要两个指令 - 它们基本上做同样的事情,但只能一起工作..?

这是一个非常肮脏的修复。我怎样才能以干净的方式解决这个问题?我不明白为什么它的行为如此不可预测。

根据在注释中进行的讨论,我们知道this.Loader是离子角Loading类的一个实例,并且它的dismiss方法至少在OP的上下文中运行时返回一个ZoneAwarePromise实例。

ZoneAwarePromise是一个专门的Promise实现,由区域创建并由区域返回.jsAngular 所依赖的库来颠覆 DOM 并重新连接异步回调和事件的编排,但我跑题了......

关键是它基本上是一个Promise,并且明确表示一个异步API。我们需要适当地与这样的 API 通信,因为以 fire 和忘记的方式使用它可能会导致计时问题,例如 OP 中指示的行为。

下面我将说明我认为基于OP代码正确重写该代码的内容。

  1. 在 TypeScript>= 2.2.0 和 ES2017 中,我们有两种方法可以利用来干净正确地处理基于承诺的 API,并确保依赖逻辑的正确执行顺序。

    async/await.这可以被认为是以后与基于乔鼎的 API 交互的首选方式,因为它提供了出色的可读性并允许标准的异常处理模型。写起来也非常简洁和愉快。

    export default class {
    async hideLoading() {
    // note we probably don't need the try wrapper
    // it is good practice to NOT handle unknown errors
    // just put it here for illustrative purposes
    try {
    await this.loader.dismiss();
    } 
    catch (e) {
    console.error(e);
    }
    }
    connectionSuccess = async () => {
    await this.hideLoading();
    const toast = Toast.create({
    message: '...',
    duration: 3000
    });
    this.nav.present(toast);
    };
    }
    
  2. 在旧版本的TypeScript中,仅--target es2015支持async/await。如果我们需要针对es5并且有一个我们无法升级的旧版本的 TypeScript(如果可能的话,你真的应该升级),那么我们可以通过以下方式编写具有相同语义的上述代码

    export default class {
    hideLoading() {
    // note we probably don't need the .catch call
    // it is good practice to NOT handle unknown errors
    // just put it here for illustrative purposes
    return this.loader.dismiss()
    .catch(e => console.error(e));
    }
    connectionSuccess = () => {
    this.hideLoading()
    .then(() => {
    const toast = Toast.create({
    message: '...',
    duration: 3000
    });
    this.nav.present(toast);
    });
    };
    }
    

这里的关键要点是,当我们与异步 API 通信时,我们必须使用异步编程模型。如果 API 是基于 Promise 的,就像这里一样,那么通过async/await使用它几乎是一个毫不费力的更改,因为我们甚至可以保留顺序异常处理机制。

如果我们在转译器或运行时中都没有async/await支持,我们可以使用Promise.prototype.thenPromise.prototype.catch来编写代码来实现相同的目标,从而以最小的麻烦完成工作。

如果 API 是基于Observable的,那么我们将需要更复杂的转换,并且无法选择使用语法糖,例如async/await.1

笔记:

  1. 在RxJS的原始语言C#和Visual Basic中,async/awaitLINQ推导都可以直接在Observable上作为语法糖进行操作。它们可能不是完美的选择,但这可能会有所帮助。在 JavaScript 中,我们没有这样的工具。

相关内容

  • 没有找到相关文章

最新更新