為什麼 Angular4 異步請求回調中設置值不觸發視圖更新?
直接上代碼先:
export class HeaderComponent {
constructor() {}
currentUser = null
signin () {
AV.User.logIn(this.model.username, this.model.password).then((loginedUser) => {
this.currentUser = loginedUser
})
}
}
這裡用 Leancloud 實現的是一個登錄的方法,登錄後,this.currentUser = loginedUser
賦值成功,但視圖並沒有更新。
在 AngularJs 1.x 中,我知道是需要主動觸發更新的,那在 Angular4 中又是怎樣觸發更新的呢?用 Observable
或者 Promise
還是其他,有沒有更便捷的方法。
測試過,Promise
是可行的,Observable
應該也可以的吧。(就是搞不懂為什麼異步回調裡賦值跟同步賦值的結果會不一樣,還要在請求外套東西)。還有方法就是用 httpClient 來請求 Leancloud 的 rest API。
Promise.resolve().then(() => {
return AV.User.logIn(this.model.username, this.model.password)
}).then((loginedUser) => {
this.currentUser = loginedUser
}).catch(() => {
})
getBusiness () {
return new Observable<any>((observer) => {
var query = new AV.Query('Business')
query.find().then((results) => {
observer.next(results)
observer.complete()
}).catch((error) => {
observer.error(error.message)
})
})
}
constructor() {
this.getBusiness().subscribe((list) => {
console.log(list)
this.business = list
})
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
太长不读版:
因为 Leancloud 用的不是 Promise。
太长也要读版:
Angular 对于异步任务的检测依赖于 Zone.js,而 Zone.js 实现的原理是事先针对 所有可能 的异步 API 进行埋点,从而劫持相应的方法以实现监听。
那么问题来了,Zone.js 如何得知所有可能的异步 API 呢?
答案当然是:没办法的。所以 Zone.js 默认只会劫持对标准的 Web API 或者 JavaScript API 中定义的异步过程,具体的列表位于 STANDARD-APIS.md 文档中。对于不在标准中的,但是有常用的第三方 API,也提供了一定的支持,具体的支持情况位于 NON-STANDARD-APIS.md 文档中。
所以很明确的一点,对于既不是标准 API,又不是 Zone.js 特别支持的常用 API 的话,是无法正确最终异步上下文的。
那么另一个问题是,Leancloud SDK 到底用的是什么呢?我们来看看源码(leancloud/javascript-sdk):
这里可以很清晰的看出,Leancloud SDK 使用的是扩展过的
es6-promise
这个 NPM Package,而且并不是作为 Polyfill 使用的,而是作为 Library 使用的。如果打开它 打包后的文件,可以看到其中有一个 Promise$2 类型:
这就是内联后的样子。所以说,对于 Leancloud SDK 而言,只是一个兼容 Promise API 的普通的第三方库,而并非 Promise。于是乎 Zone.js 对此当然也是无能为力的。
所以简单地说,就是 Leancloud 自己的实现过于 Tricky 且远离现有的 Web 规范,不被支持很正常。
那虽然不是 Angular 的问题,要如何补救呢?
最简单的方案是使用 NgZone#run() 方法进行包装,形如:
这样就能重新将异步上下文重置为 Angular 内,以保证得到正确的监听。
建议提供HTML模板,才能分析。线等!