Part 3: Using a Service

To perform the retrieval of RSS data from a remote server, we will define our own Service. In webOS, Services are used to generate asynchronous requests to servers both local (DB, device info) and remote (Web).

In our sample application, we will use a WebService. (The WebService kind is derived directly from enyo.Service.)

We'll declare our service in the components block of FeedReader.js:

components: [
  {name: "getFeed", kind: "WebService",
      onSuccess: "gotFeed",
      onFailure: "gotFeedFailure"},
  {kind: "PageHeader", content: "Enyo FeedReader"},
  {kind: "RowGroup", caption: "Feed URL", components: [
      {kind: "InputBox", components: [
          {name: "feedUrl", kind: "Input", flex: 1, 
              value: "http://feeds.bbci.co.uk/news/rss.xml"},
          {kind: "Button", caption: "Get Feed", onclick: "btnClick"}
      ]}
  ]}
],

The declaration includes the name of our Service ("getFeed"), its kind ("WebService"), and the names of the (yet-to-be-created) methods to be called if our asynchronous request succeeds or fails ("gotFeed" and "gotFeedFailure", respectively).

Since we want a tap of the Get Feed button to trigger the asynchronous request, the triggering code will go inside the btnClick method:

btnClick: function() {
  var url = "http://query.yahooapis.com/v1/public/yql?q=select"
      + "%20title%2C%20description%20from%20rss%20where%20url%3D%22"
      + this.$.feedUrl.getValue() + "%22&format=json&callback=";
  this.$.getFeed.setUrl(url);
  this.$.getFeed.call();
},

The getFeed WebService needs to have its url property set before it can begin a request through getFeed.call. In this case, the value of url is actually the location of a public Yahoo API that will query the RSS server (i.e., the user-supplied URL extracted from the Input) and return the title and description data in JSON format.

The dollar sign notation (this.$) is a shorthand representation of the hash of all components owned by this (i.e., our FeedReader object). Individual components may be accessed by name, as this.$.componentName. In btnClick, for example, we use this.$.getFeed to refer to the getFeed WebService.

This shorthand may also be used with components that are not explicitly named. For instance, we could access the PageHeader object as this.$.pageHeader even though we did not assign a name to it. The (camel-cased) pageHeader variable is automatically created for us by Enyo. If we had given the PageHeader a name--say, "mySuperPageHeader"--it would instead be available to us as this.$.mySuperPageHeader.

An additional thing to note is that we've added a value property to our Input:

value: "http://feeds.bbci.co.uk/news/rss.xml"

This will expedite our testing by prepopulating the text input box with the URL for retrieving the top news stories from the BBC.

At this point, we've added all the code we need to make our asynchronous request. Ultimately, of course, we'll need to parse and display the returned data, but first let's verify the success or failure of the request.

We can create a quick and dirty indicator of our WebService call's success or failure by temporarily defining gotFeed and gotFeedFailure like so:

gotFeed: function(inSender, inResponse) {
  this.$.button.setCaption("Success");
},
gotFeedFailure: function(inSender, inResponse) {
  this.$.button.setCaption("Failure");
}

Because caption is a published property of the Button kind, Enyo automatically generates (again, camel-cased) getter and setter methods for it, so we are able to call setCaption without having to explicitly declare the method. (For more information, see Published Properties.)

Now when the service call completes, the text of the Get Feed button will be updated to read either "Success" or "Failure". BBC willing, you should be able to see in your browser that the request is completing successfully.

By this point, you've probably noticed that our FeedReader contains no UI for showing the returned data, so that's the next item on our agenda.

(Continue to Part 4: Displaying Data.)