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

Javascript 为什么我需要键入两次此命令才能在Typescript,Ionic 2中工作?,javascript,typescript,ionic-framework,ionic2,Javascript,Typescript,Ionic Framework,Ionic2,我已经搜索了两个小时的问题,我的回调函数并没有关闭离子2中的LoadingController 我有一个函数,hideLoading(): 在success函数中调用 connectionSuccess = () => { this.hideLoading(); var toast = Toast.create({ message: '...', duration: 3000}); this.nav.present(toast);

我已经搜索了两个小时的问题,我的回调函数并没有关闭离子2中的LoadingController

我有一个函数,hideLoading():

在success函数中调用

connectionSuccess = () =>
{
    this.hideLoading();

    var toast = Toast.create({
        message: '...',
        duration: 3000});

    this.nav.present(toast);
}
由于某种原因,它不起作用。。但我刚刚发现它是有效的——如果我在两者之间加上一个alert();或者,如果我将代码更改为:

connectionSuccess = () =>
{
    this.hideLoading();
    this.loader.dismiss();
    [...] 
}
这是与时间有关的错误吗?alert()的时间介于两者之间或第二条hide指令似乎可以解决此问题。。在解散之前,我在控制台日志中检查了
this.loader
的内容,它完全正确

如果我删除上面两个说明中的一个,它将不起作用。它需要两个指令——它们基本上做相同的事情,但只是一起工作


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

根据在评论中进行的讨论,我们知道
this.Loader
是一个ionic angular
加载类的实例,它的
dislose
方法返回一个
ZoneAwarePromise
实例,至少在OP的上下文中运行时是这样

ZoneAwarePromise
是一个专门的
Promise
实现,它是为zone.js创建并由其返回的,Angular依赖该库来破坏DOM并重新编排回调和事件的异步编排,但我偏离了主题

关键是它基本上是一个
承诺
,并且明确表示一个异步API。我们需要适当地与这样一个API进行对话,例如在火中使用它,而忘记方式可能会导致时间问题,例如OP中所指示的行为

下面我将根据OP的代码说明我认为正确的代码重写

  • 在TypeScript>=2.2.0和ES2017中,我们可以利用两种方法干净、正确地处理基于承诺的API,并确保相关逻辑的正确执行顺序

    异步
    /
    等待
    。这可以被认为是未来与基于承诺的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);
      };
    
    }
    
  • 在旧版本的TypeScript中,
    async
    /
    await
    仅支持
    --target es2015
    。如果我们需要将
    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是基于承诺的,比如这里的API,那么通过
    async
    /
    await
    使用它几乎是一个毫不费力的更改,因为我们甚至可以保留顺序异常处理机制

    如果我们在transpiler或运行时中都没有
    async
    /
    await
    支持,那么我们可以使用
    Promise.prototype.then
    Promise.prototype.catch
    来编写代码,以尽可能少的麻烦完成任务

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

    注:

  • 在RxJS的源语言C#和Visual Basic中,
    异步
    /
    等待
    和LINQ理解都可以直接在
    可观察
    上作为语法糖进行操作。它们可能并不完美,但这可能会有所帮助。在JavaScript中,我们没有这样的功能

  • 这个.loader
    是什么,调用
    会在返回时忽略它什么<代码>未定义
    ?一个
    承诺
    ?可观察到的
    ?您可能缺少一个
    wait
    、一个
    return
    、一个
    subscribe
    ,但从提供的信息很难判断。@AluanHaddad
    这个。loader
    是ionic 2的
    加载
    类的一个实例。
    dislose()
    方法返回
    ZoneAwarePromise{…}
    。Await听起来不错,但我在方法调用前面放置Await时遇到语法错误。这似乎确实是一个异步/等待问题,因为在两者之间放置警报可以解决此问题。。编辑:我尝试了alert(),但它不再修复它。。但就在之前,它在之间使用了一个alert()。好吧,它返回一个承诺,然后使用
    async hideLoading(){wait this.loader.dismise();}
    然后需要在调用
    hideLoading
    的方法中等待它。您还可以使用
    然后
    并显式返回结果。wait是更可读的选项。仅供参考,alert工作的原因可能是alert是一种罕见的浏览器API,它实际上会阻止事件循环。不确定原因,可能您没有使用最新的TypeScript(使用>=2.2.1)。无论如何,您可以不用
    异步
    /
    等待
    完成相同的任务。然后
    捕获
    这对我来说很有效,非常感谢!我不知道应该如何使用.then(),但现在它很有意义。很高兴我能帮上忙
    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);
          });
      };
    
    }