正确使用 Promise.resolve().then() 错误:未捕获(在承诺中):TypeError:无法读取属性

Posted

技术标签:

【中文标题】正确使用 Promise.resolve().then() 错误:未捕获(在承诺中):TypeError:无法读取属性【英文标题】:Using Promise.resolve().then() correctly Error: Uncaught (in promise): TypeError: Cannot read property 【发布时间】:2020-04-29 18:11:43 【问题描述】:

我有这个代码:


export class Page 
  constructor(public modalController: ModalController)  

  private async openModal(value)     
    const modal = await this.modalController.create(
      component: AnotherPage,
      componentProps: 
        "paramID": 123,
        "paramTitle": "Test Title",
        "takenPhoto": "null"
      
    );

    return await modal.present();
  

  public async takePicture() 
    this.openModel(null); // here's OK
    Promise.resolve(this.someMethod()).then(this.openModal); // ERROR!!
  



takePicture 方法上,我想在执行Promise.resolve 之后打开一个模式。在第一次执行时一切正常,但在第二次执行时出现错误。

错误:

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'modalController' of undefined
TypeError: Cannot read property 'modalController' of undefined
    at tab2.page.ts:25
    at Generator.next (<anonymous>)
    at tslib.es6.js:73
    at new ZoneAwarePromise (zone-evergreen.js:876)
    at Module.__awaiter (tslib.es6.js:69)
    at openModal (tab2.page.ts:22)
    at ZoneDelegate.invoke (zone-evergreen.js:359)
    at Object.onInvoke (core.js:34201)
    at ZoneDelegate.invoke (zone-evergreen.js:358)
    at Zone.run (zone-evergreen.js:124)
    at resolvePromise (zone-evergreen.js:797)
    at resolvePromise (zone-evergreen.js:754)
    at zone-evergreen.js:858
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:34182)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at drainMicroTaskQueue (zone-evergreen.js:559)

【问题讨论】:

这能回答你的问题吗? How to access the correct `this` inside a callback? 既然 takePicture 方法是异步的,你不能先等待 this.someMethod 再继续执行 this.openModal 吗? @tlm 我不这样,因为 this.someMethod() 返回一个 Promise,所以我必须使用 Promise.resolve(...).then(resolveFunction(value) ) 获取对象value。但不得不说……我最近开始用typescript,也许还有别的方法 提供您创建Page 实例的方式。 【参考方案1】:
export class Page 
  constructor(public modalController: ModalController)  

  private async openModal(value)     
    const modal = await this.modalController.create(
      component: AnotherPage,
      componentProps: 
        "paramID": 123,
        "paramTitle": "Test Title",
        "takenPhoto": "null"
      
    );

    return modal.present();
  

  public async takePicture() 
    await this.openModel(null); // Need to await a promise
    const data = await this.someMethod()
    await this.openModal(data);
  


【讨论】:

【参考方案2】:

为什么会发生错误? 这是因为如果您想在一个隐式函数调用中调用“this”,您必须将这个调用绑定到“this”状态。看看吧:

之前:

  public async takePicture() 
    this.openModel(null); // here's OK
    Promise.resolve(this.someMethod()).then(this.openModal); // ERROR!!
  

之后:

  public async takePicture() 
    this.openModel(null); // here's OK
    Promise.resolve(this.someMethod()).then(this.openModal.bind(this)); // JUST FINE :)
  

现在隐式调用将接收到 this 状态以在此处正确使用:

await this.modalController.create(...

Se precisar de ajuda em pt-BR pod mandar msg :)

【讨论】:

【参考方案3】:

根据@VLAZ 所说的(我建议阅读他提供的链接),您假设this 在 openModal() 函数的上下文中引用了类的上下文。由于this 的值仅取决于函数的“调用方式”,因此this.modalControllerthis 的出现尚未绑定到上下文,因此this 变为未定义,这就是原因你得到了错误。

您可以在调用函数之前将this 设置为类的上下文。以下是一些方法:

1 - 在构造函数中绑定this

constructor(public modalController: ModalController) 
    this.openModal = this.openModal.bind(this);

2 - 使用箭头函数自动将this 绑定到类的上下文(父上下文)。

openModal = async (value) =>     
    const modal = await this.modalController.create(
       component: AnotherPage,
       componentProps: 
           "paramID": 123,
           "paramTitle": "Test Title",
           "takenPhoto": "null"
       
     );

     return modal.present();

我认为还有其他方法可以做到这一点,但这些方法已被广泛接受。 希望对您有所帮助!

【讨论】:

以上是关于正确使用 Promise.resolve().then() 错误:未捕获(在承诺中):TypeError:无法读取属性的主要内容,如果未能解决你的问题,请参考以下文章

Promise.resolve 与新的 Promise(resolve)

Promise.resolve()的参数分4种情况

.resolve() 和 .promise() 有啥区别?

Promise.resolve()与new Promise(r =; r(v))

为啥链接到 Promise.resolve() 的 .then() 允许重新分配 const 声明?

Promise.resolve 是异步函数吗?