【问题标题】:Async function returning promise, but calling function not resolving异步函数返回承诺,但调用函数未解析
【发布时间】:2019-12-31 20:14:54
【问题描述】:

到目前为止,我已经在这里研究了其他类似的项目但没有结果,显然需要更好地理解承诺,但我在这里挣扎。

我有一个带有基于 Azure 的后端的 Ionic 4/Angular 8 项目。 我正在尝试让页面显示来自 Azure 存储的图像,这需要将密钥附加到 url。

为了避免在每个页面中使用“检查键,如果过期,获取一个新的,附加到 url”代码,我想我会创建一个服务功能来做到这一点。但是虽然我可以让它工作,但调用函数似乎并没有在等待'.then',所以我变得不确定。 (我想)。理想情况下,我希望服务只返回一个字符串

我拥有的服务功能(带有一些 cmets 和调试 o/p)是这样的:

   // Ideally I'd like to just return a string here ---v
 // v- but the async nature needs async return type ??
 async getStorageURLWithKey(url: string): Promise<string> {
  const nowplus5 =  addMinutes(Date.now(), 5); // 5 mins to give some leeway
  console.log(nowplus5);
  console.log(url);
  console.log(this.azurekey);
  if (!this.azurekey || isBefore( this.azurekey.Expires, nowplus5 )) {
    console.log('Getting new Key');
    const keyObj = await this.getAzureKeyServer().toPromise();
    await this.saveAzureKeyStore(keyObj);
    return url + keyObj.Key; // Return the url with the new Key
  } else {
    console.log('Key is valid' + this.azurekey.Expires);
    const rval = new Promise<string>(function(res) {
      res(url + this.azurekey.Key);
    });
    return rval ; // Key is in time so return it with url
  }
 }

我的调用函数是这样的:

getBizImg(): string {
  console.log('GetBizImg');
  if (this.business.Id) {  // We have a Business Object
    this.userService.getStorageURLWithKey(this.business.ImageURL).then((url) => {
      console.log(url);
      return url;
    }, reject => {
      console.log('Rejected:' + reject);
    });
  } else {
    return '';
  }
}

如果我从 ngOninit 调用 getBizImg 函数,它会在 getBizImg - console.log(url) 行之前返回未定义。

这里是 ngOninit:

ngOnInit() {
  const imageurl = this.getBizImg();
  console.log(imageurl);
}

真的应该是来自页面的调用:

<ion-content padding>
   <ion-img [src]="getBizImg()" ></ion-img>
</ion-content>

但我已经对此进行了评论,直到我可以解决这个问题。否则它会进入一个看似无止境的循环。

如果我将 getBizImg() 转换为异步函数并等待调用并返回一个承诺,它可以正常工作 - 如果我将我的 ngInit 修改为:

ngOnInit() {
  this.getBizImg().then((wibble) => {
    console.log(wibble);
  });
}

和 getBizImg 函数:

async getBizImg(): Promise<string> {
  console.log('GetBizImg ID= ' + this.business.Id);
   if (this.business.Id) {  // We have a Business Object
     const url = await this.userService.getStorageURLWithKey(this.business.ImageURL);
     console.log(url);
     return url;
   } else {
     return '';
   }
 }

但这不会让我得到 HTML 所需的简单字符串。

我不确定我是否遗漏了一些(可能)明显的东西......

**** 编辑更新**** 我已尝试更改为完全异步并包括角度异步管道:

<ion-content padding>
  BIZ IMAGE
<ion-img [src]="getBizImg() | async" ></ion-img>

我也尝试只显示字符串:URL is: {{ getBizImg() | async }}

但它进入了一个(看似无限循环)。不过这很奇怪,因为它正在访问 this.getAzureKeyServer() 函数,但我没有遇到我在 GetKey API 调用时在服务器代码中设置的断点。

这让我走上了一条不同的道路,以进一步检查页面功能。我取消了对后端的调用,只返回一个这样的字符串:

<ion-content padding>
  BIZ IMAGE
  URL is: {{ getBizImg() | async }}
</ion-content>

  async getBizImg(): Promise<string> {
    console.log('GetBizImg ID= ' + this.business.Id);
    if (this.business.Id) {  // We have a Business Object
      const url = 'wibble'; // this.business.ImageURL;
      // const url = await this.userService.getStorageURLWithKey(this.business.ImageURL);
      console.log(url);
      return url;
    } else {
      console.log('invalid id');
      return 'invalid id';
    }
  }

...这也进入了一个无限循环,所以我认为有一些更根本的事情正在发生...我的意思是我在这里犯了某种小学生错误?

【问题讨论】:

标签: javascript angular typescript ionic-framework


【解决方案1】:

我认为您的异步 getBizImg() 是正确的。你可以这样做

ngOnInit() {
  this.getBizImg().then((wibble) => {
    console.log(wibble);
    // just add here this.urlImage = wibble
  });
}

在你的组件上添加一个 urlImage。 并在 html

<ion-content padding>
   <ion-img *ngIf="urlImage" [src]="urlImage" ></ion-img>
</ion-content>

或者如果你想从 html 中调用它,我不确定但可以试试 asyncPipe https://angular.io/api/common/AsyncPipe

<ion-content padding>
   <ion-img [src]="getBizImg() | async" ></ion-img>
</ion-content>

【讨论】:

  • 谢谢你,你是对的......我的问题不在于我的代码,而在于方法和对角度的误解。当我删除对后端的调用时,情况变得更加清晰(可能一开始就应该这样做 - 但在这里没有意识到这个问题:stackoverflow.com/questions/41265716/…)。
【解决方案2】:

getBizImg() 从不返回 URL,因为您只在 getStorageURLWithKey() 承诺的回调中返回它。

返回该承诺(并将方法类型更改为 Promise&lt;string&gt; 并使用异步管道显示它:

getBizImg(): string {
  console.log('GetBizImg');
  if (this.business.Id) {  // We have a Business Object
    // return here
    return this.userService.getStorageURLWithKey(this.business.ImageURL).then((url) => {
      console.log(url);
      return url;
    }, reject => {
      console.log('Rejected:' + reject);
    });
  } else {
    return '';
  }
}
<ion-content padding>
   <ion-img [src]="getBizImg() | async"></ion-img>
</ion-content>

【讨论】:

  • 谢谢你,Thomas,我在上面的 ext 中放了一个 Edit Update .. 把它简化了。所以我认为我的问题与异步管道有关。它需要设置吗?
  • 通过剥离解决了这个问题,并意识到问题不在于代码,而在于方法和对角度更改管理的误解 - 请参见此处:stackoverflow.com/questions/41265716/…,但还是谢谢你。
猜你喜欢
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2016-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多