Using Promises

To support asynchronous API execution, Kii Cloud SDK supports the implementation with Promises besides callback function.

JavaScript SDK provides features that will consume time (e.g., creating a new user and uploading data) as non-blocking APIs. When leveraging these features, you can use either the Promises or callback function to run the processes asynchronously and get the execution results when the processes are done.

You can use either Promises or callback functions to specify what to do when the asynchronous execution is done.

  • Promises

    You can specify the consequent process of non-blocking APIs using Promises.

    APIs that access the network will return a Promise object that conforms to the Promises/A+ specification. By writing your application with Promises, you can make your code clean without too much nesting (compared to when you write your code with callback functions).

    KiiUser.authenticate("user_123456", "123ABC").then(
      function(theAuthenticatedUser) {
        // Do something with the authenticated user.
      },
      function(error) {
        // Do something with the error response.
      }
    );
    
  • Callbacks

    You can pass a callback function to the SDK when you execute an API. The SDK will call the callback function when the API execution is done.

    This is very simple, but you might end up with many nesting when you are to call multiple APIs in sequence (aka. "callback hell").

    KiiUser.authenticate("user_123456", "123ABC", {
      success: function(theAuthedUser) {
        // Do something with the authenticated user.
      },
      failure: function(theUser, anErrorString) {
        // Do something with the error response.
      }
    });
    

We recommend you to use Promises feature. The Promises will allow you to code a complex processes simple.

There are many Promise specifications available on JavaScript. Kii JavaScript SDK adopts the Promises/A+ specification. Some method names are different among Promise specifications, so be careful when you are referring external sites.

You can use both Promises or callbacks when calling an API, but you should not mix them. When using Promises, for example, make sure not to pass a callback function when calling the API. It is perfectly ok for your application to use Promises in some portion and callback functions in other portion.

Examples

Let us see two pieces of sample code, one written with callback functions and another written with Promises.

Here, we are just comparing implementation with callbacks and Promises. Please refer to the corresponding references for the detailed explanation of the APIs used in the sample code.

Example with callback functions

This is a sample code block with callback functions.

In this sample code, we are calling the following three APIs:

  1. Call the authenticate method for the user login.
  2. When the user login is successful, call the save method to create an object with the data score = 987 in the app_bucket bucket.
  3. When the object creation is successful, call the listACLEntries method to get the ACL of the object.

When implementing this kind of sequential API calls, you need to write the consecutive processes in the success callback function. Because of this, the nesting in your code will get deeper as more APIs are called. Having many nestings make your code messy and hard to track the failure callback functions.

// 1. Log in the user.
KiiUser.authenticate("user_123456", "123ABC", {
  success: function(theAuthedUser) {
    // 2. Create a KiiObject.
    var appBucket = Kii.bucketWithName("app_bucket");
    var obj = appBucket.createObject();
    obj.set("score", 987);
    obj.save({
      success: function(theObject) {
        // 3. Get the ACL.
        var acl = theObject.objectACL();
        acl.listACLEntries({
          success: function(theACL, theEntries) {
            console.log("ACL got!");
            console.log(JSON.stringify(theEntries));
          },
          failure: function(theACL, errorString) {
            console.log("Error listing ACL: " + errorString);
          }
        });
      },
      failure: function(theObject, errorString) {
        console.log("Error saving object: " + errorString);
      }
    });
  },
  failure: function(theUser, anErrorString) {
    console.log("Error authentication: " + errorString);
  }
});

Example with promises

This is a sample code block with Promises and it is equivalent to the previous sample code with callbacks.

Like the previous sample code, we are calling the authenticate, save, and listACLEntries methods sequentially.

As you can see in the sample code, we are connecting a series of processes with Promise objects that the APIs return. This format allows us to avoid the deep nesting and also to clarify the flow of the processes. You can also aggregate error handling in one place (you can, of course, handle the errors individually if you want).

// 1. Log in the user.
KiiUser.authenticate("user_123456", "123ABC").then(
  function(params) {
    // 2. Create a KiiObject.
    var appBucket = Kii.bucketWithName("app_bucket");
    var obj = appBucket.createObject();
    obj.set("score", 123);
    return obj.save();
  }
).then(
  function(theSavedObject) {
    // 3. Get the ACL.
    var acl = theSavedObject.objectACL();
    return acl.listACLEntries();
  }
).then(
  function(params) {
    console.log("ACL got!");

    var theEntries = params[1];
    console.log(JSON.stringify(theEntries));
  }
).catch(
  function(error) {
    console.log("Error: " + error);
  }
);

Note that you will miss the error handling if you do not write the catch handler. The catch handler is important especially when you are writing server code; failing to execute the done() when an error occurs will cause a timeout. For more information about the done() function in server code, see Asynchronous execution.