尝试使用Provider从firebase服务器获取数据,该服务器使用4级嵌套回调函数。以下是我的提供商的样子。
import { Injectable } from '@angular/core';
declare var window;
@Injectable()
export class SettingsProvider {
constructor() {
}
public async getFireBaseRemoteConfig(): Promise<any> {
if (window["FirebasePlugin"]) {
await window["FirebasePlugin"].fetch(600, async result => {
// activate the fetched remote config
console.log(JSON.stringify(result)); //Always "OK"
await window["FirebasePlugin"].activateFetched( async (bool) => {
await this.getSliderImageURLs().then((d) => {
console.log("d", d);
return d;
});
});
})
}
}
public async getSliderImageURLs(): Promise<any> {
var urls = [];
await window["FirebasePlugin"].getValue("slider_images", result => {
urls = JSON.parse(result);
console.log("FROM getSliderImageURLs()");
console.log(urls)
return Promise.resolve(urls);
})
}
}
我期望执行的顺序是getFireBaseRemoteConfig函数仅在getSliderImageURLs函数获取数据并返回时才返回。
根据文档,函数应按此顺序执行:
fetch - &gt; activateFetched - &gt;的getValue
在我的页面中,我正在使用它。
console.log(this.settingsProvider.getFireBaseRemoteConfig()); // Just for testing
我做错了什么?任何帮助都非常感谢。
编辑:添加了控制台日志
OK
d undefined
FROM getSliderImageURLs()
["","","",""] //this is my URLs array
答案 0 :(得分:2)
看起来你正在使用传统的promise结构和async / await错误地在一起。您可以或使用Async / await(下面的答案1,但是你必须将回调转换为promises)或者你可以使用传统的promises(回答2),或者使用新的离子本机firebase插件(回答3)来转换回复承诺给你。
当你使用异步等待时,代码将像同步一样执行,因此不需要在异步等待中使用.then()。你的代码将变成这样的东西。
public async getFireBaseRemoteConfig(): Promise<any> {
if (window["FirebasePlugin"]) {
let remoteConfig = await window["FirebasePlugin"].fetch(600);
let sliderImageUrls = await this.getSliderImageURLs();
// From here you can do whatever you want with remoteConfig & sliderImageUrls, as they are resolved with async/await
return sliderImageUrls;
}
public async getSliderImageURLs(): Promise<any> {
let sliderImagesJson = await window["FirebasePlugin"].getValue("slider_images")
let sliderImages = JSON.parse(sliderImagesJson);
return Promise.resolve(sliderImages);
})
}
这种await / async方法仅在链接promises时才会优先,在你的情况下链接回调。因此,对于这个工作的答案,你需要将回调更改为这样的承诺:
//Convert the fetch Remote Config callback to a promise
public getRemoteConfig(cacheExpirationSeconds:number=600):Promise<any> {
return new Promise<boolean>((resolve, reject) => {
window["FirebasePlugin"].fetch(cacheExpirationSeconds,(result) => resolve(result))
});
}
在您的示例中,我建议采用更传统的承诺结构,如下所示:
传统承诺结构(没有异步/等待)
public getFireBaseRemoteConfig(): Promise<any> {
return new Promise<any>((resolve, reject) => {
if (window["FirebasePlugin"]) {
window["FirebasePlugin"].fetch(600, (result) => {
// activate the fetched remote config
console.log(JSON.stringify(result)); //Always "OK"
window["FirebasePlugin"].activateFetched((bool) => {
this.getSliderImageURLs().then((d) => {
console.log("d", d);
resolve(d);
});
});
})
}
else {
reject();
}
});
}
// getSlider函数:
public getSliderImageURLs(): Promise<any> {
return new Promise<any>((resolve, reject) => {
var urls = [];
window["FirebasePlugin"].getValue("slider_images", (result) => {
urls = JSON.parse(result);
console.log("FROM getSliderImageURLs()");
console.log(urls)
resolve(urls);
});
});
}
使用新的(目前处于测试阶段)firebase原生插件,它已经将回调转换为承诺,因此您可以使用答案1.
编辑:一个澄清传统承诺与传统之间差异的例子。同步/等待
传统承诺结构中的一个例子:
getPrice(currency: string): Promise<number> {
return this.http.get(this.currentPriceUrl).toPromise()
.then(response => response.json().bpi[currency].rate);
}
与async / away相同:
async getPrice(currency: string): Promise<number> {
const response = await this.http.get(this.currentPriceUrl).toPromise();
return response.json().bpi[currency].rate;
}
的来源
希望这有帮助