Promise の利用
Kii Cloud SDK for JavaScript では、API の非同期的な実行をサポートしています。
Java Script SDK では、時間がかかる API をノンブロッキング API で実現しています。新規ユーザーの登録やデータのアップロード等、SDK が提供する多くのメソッドはサーバーとの通信が発生する関係で処理完了までに時間を要します。これらの処理は非同期に行い、処理完了後の動作は、以下のように Promise またはコールバック関数で記述できます。
基本的には Promise を使って実装してください。
コールバック関数を用いた記述は Kii Cloud SDK for JavaScript の v2 系でのみ利用可能です。v3 系では利用できません。
Promise
Promise を使ってノンブロッキング API の処理を記述できます。
ネットワークアクセスを行う各 API は Promises/A+ に準拠した Promise オブジェクトを返します。アプリでは Promise に基づいた処理を記述することで、下記のコールバック関数のようにネストが深くなる問題を回避できます。
KiiUser.authenticate("user_123456", "123ABC").then( function(theAuthenticatedUser) { // Do something with the authenticated user. }, function(error) { // Do something with the error response. } );
JavaScript で利用できる Promise の記述方法は様々な形式がありますが、Kii JavaScript SDK では今後主流になると思われる Promises/A+ を採用しています。使用する Promise の実装により、メソッド名などの書式が異なるものがあるため、一般のサイトから情報を探す場合にはご注意ください。
コールバック関数
処理が完了した際に実行される関数を API に渡すと、API の実行完了時に SDK 側から呼び出します。
シンプルな仕組みですが、複数の API を順番に呼び出す処理を記述すると、ネストが非常に深くなる問題(いわゆる「コールバック地獄」)が発生します。
KiiUser.authenticate("user_123456", "123ABC", { success: function(theAuthedUser) { // Do something with the authenticated user. }, failure: function(theUser, anErrorString) { // Do something with the error response. } });
API の書式上、各 API は Promise とコールバックの両方を記述できるようになっていますが、どちらか一方を選択して実装します。たとえば、Promise を使う場合、API の呼び出し時にコールバック関数を渡さないようにしてください。なお、アプリ内の実装箇所によって、Promise を使う部分と、コールバックを使う部分が混在する使い方は問題ありません。
実装例(Promise とコールバック関数による実装の比較)
以下にコールバック関数と Promise を使ったアプリの実装例を示します。
以下の例で使用している各 API の使用方法は、本ガイドの詳細ページで順に解説します。ここでは Promise を使う場合の利点のみをご確認ください。
コールバック関数による実装例
コールバック関数を使ったアプリの実装例を以下に示します。
このアプリでは 3 回の API 呼び出しを行っています。
authenticate
によってユーザーをログイン- 成功したときは
app_bucket
上にscore = 987
というデータを持った Object をsave
によって作成 - さらに成功したときは
listACLEntries
によって、今、作成した Object の ACL を取得してアクセス権を確認
連続する処理を実現するには、成功のコールバック関数内に次の処理を記述する必要があるため、API を呼び出すたびにネストが深くなり、プログラムの見通しが悪くなっていきます。同時に、API の失敗時に実行されるコールバック関数との対応も取りづらくなります。
// 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);
}
});
Promise による実装例
Promise を使って、上記のサンプルと同じ機能を実装した例を以下に示します。
コールバック関数を使う例と同様に、authenticate
、save
、listACLEntries
を順に呼び出しています。
ここでは、各 API が返した Promise を使って、処理の連鎖を構築しています。ネストが深くなる現象を回避できると同時に、上から下への処理の流れが明確になります。また、エラー処理をまとめることもできるため(個別に記述することもできます)、正常系の見通しがよくなります。
// 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);
}
);
なお、catch ハンドラーを記述しておかないと、エラー発生時の処理を取りこぼすことになります。特に、Server Code で動作させる場合は、エラー発生時に処理の完了を表す done()
を呼び出すタイミングを失い、処理がタイムアウトすることになるため、ご注意ください。Server Code での done()
の詳細は こちら をご覧ください。