我已经搜索了 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代码正确重写该代码的内容。
-
在 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); }; }
-
在旧版本的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.then
和Promise.prototype.catch
来编写代码来实现相同的目标,从而以最小的麻烦完成工作。
如果 API 是基于Observable
的,那么我们将需要更复杂的转换,并且无法选择使用语法糖,例如async
/await
.1
笔记:
- 在RxJS的原始语言C#和Visual Basic中,
async
/await
和LINQ推导都可以直接在Observable
上作为语法糖进行操作。它们可能不是完美的选择,但这可能会有所帮助。在 JavaScript 中,我们没有这样的工具。