到目前为止,我在这里还研究了其他类似的项目,但是没有结果,显然需要更好地理解诺言,但是我在这里苦苦挣扎。
我有一个基于Ionic 4 / Angular 8的项目以及基于Azure的后端。 我正在尝试让页面显示来自Azure存储的图像,这需要在URL后面附加一个密钥。
为避免在每个页面中都有'check key,如果过期则获取一个新的key,追加到url'代码,我想我应该做一个服务函数来做到这一点。但是,尽管我可以使它正常工作,但调用函数似乎并没有在'.then'上等待,因此我无法定义。 (我认为)。理想情况下,我希望该服务仅返回一个字符串
我具有的服务功能(带有一些注释和调试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';
}
}
...这也陷入了一个无休止的循环,所以我认为还有一些更根本的事情在发生...我是说我在这里犯了某种小学生错误?
答案 0 :(得分:1)
getBizImg()
永远不会返回URL,因为您只能在getStorageURLWithKey()
Promise的回调中返回它。
返回承诺(并将方法类型更改为Promise<string>
并使用异步管道显示它:
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>
答案 1 :(得分:0)
我认为您的异步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>