在 Ionic 应用程序加载时显示来自 Firebase 的数据

问题描述:

我是 Ionic 和 Firebase 的初学者.为了学习使用 ionic+firebase,我正在编写一个 RandomQuote 应用程序来从 Firebase 中获取一个随机条目.当我单击重新加载按钮时会调用 reload() 方法,并且随机引用按预期显示.

I'm a beginner in Ionic and Firebase. To learn using ionic+firebase, I'm writing a RandomQuote app to fetch a random entry from Firebase. A reload() method is called when I click a reload button, and the random quote is displayed as expected.

但是,我还希望在加载应用程序时显示引用,即在我单击重新加载按钮之前.我在构造函数中调用了 reload() 方法,但它不起作用.我试图在网上搜索答案,但找不到任何我能理解的东西.不确定我是在搜索错误的关键字还是在错误的域中.

However, I also want the quote to display when the app is loaded, i.e., before I click the reload button. I call the reload() method in the constructor but it doesn't work. I have tried to search for answers on the web but cannot find anything that I could understand. Not sure if I'm searching the wrong keywords or in the wrong domains.

以下是我放入 FirebaseProvider 类并从 home.ts 调用的 reload() 方法:

The following is the reload() method that I put in my FirebaseProvider class and called from my home.ts:

reload(){
    this.afd.list('/quoteList/').valueChanges().subscribe(
      data => {
        this.oneQuote = data[Math.floor(Math.random() * data.length)];
      }
    )
    return this.oneQuote;
}

谁能给我一些提示?或者任何对初学者有用的书籍/材料的指针也将受到高度赞赏.非常感谢.

Can anyone give me some hints? Or any pointer to useful books / materials for beginners will also be highly appreciated. Thank you very much.

数据从 Firebase 异步加载.这意味着当您的 return 语句运行时 this.oneQuote 还没有值.

Data is loaded from Firebase asynchronously. This means that by the time your return statement runs this.oneQuote doesn't have a value yet.

通过在您的代码周围放置一些日志语句,最容易说出来:

This is easiest to say by placing a few log statements around your code:

console.log("Before subscribing");
this.afd.list('/quoteList/').valueChanges().subscribe(
  data => {
    console.log("Got data");
  }
)
console.log("After subscribing");

运行此代码时,输​​出为:

When you run this code, the output is:

订阅前

订阅后

获得数据

这可能不是您所期望的.但这完全解释了为什么您的 return 语句不返回数据:该数据尚未加载.

This is probably not what you expected. But it completely explains why your return statement doesn't return the data: that data hasn't been loaded yet.

因此您需要确保需要数据的代码在加载数据后运行.有两种常见的方法可以做到这一点:

So you need to make sure your code that needs the data runs after the data has been loaded. There are two common ways to do this:

  1. 通过将代码移动到回调中

  1. By moving the code into the callback

通过返回一个 promise/subscription/observable

By returning a promise/subscription/observable

将代码移到回调中是最简单的:当 console.log("Got data") 语句在上面的代码中运行时,保证数据可用.所以如果你把需要数据的代码移到那个地方,它可以毫无问题地使用数据.

Moving the code into the callback is easiest: when the console.log("Got data") statement runs in the code above, the data is guaranteed to be available. So if you move the code that requires the data into that place, it can use the data without problems.

返回一个 promise/subscription/observable 有点难理解,但是做同样的事情更好.现在不是将需要的代码数据移动到回调中,而是返回某物"在数据可用时公开数据的回调.在 AngularFire 的情况下,最简单的方法是返回实际的 observable 本身:

Returning a promise/subscription/observable is a slightly trickier to understand, but nicer way to doing the same. Now instead of moving the code-that-needs-data into the callback, you'll return "something" out of the callback that exposes the data when it is available. In the case of AngularFire the easiest way to do that is to return the actual observable itself:

return this.afd.list('/quoteList/').valueChanges();

现在需要引号的代码只需订阅返回值并更新 UI:

Now the code that needs the quotes can just subscribe to the return value and update the UI:

reload().subscribe(data => {
  this.oneQuote = data[Math.floor(Math.random() * data.length)];
}

最后一点:使用 reload() 方法听起来像是一种反模式.只要quoteList 中的数据发生变化,订阅就已经被调用.无需为此调用 reload().

A final note: having a reload() method sounds like an antipattern. The subscription will already be called whenever the data in the quoteList changes. There is no need to call reload() for that.