Parse.comを使ったサーバサイド実装不要のフロントエンド開発[後編]


parse

本記事はParse.comを使ったサーバサイド実装不要のフロントエンド開発[前編]の後編です。前編では、Parseの管理画面と、JavaScript SDKのうちBackbone.jsをベースとしている部分とCollectionの生成に必要となるデータの取得方法をご紹介しました。
後編では引き続き、ParseのJavaScript SDKの機能として以下の3つをご紹介いたします。

  • Parse.User: アカウント管理
  • Parse.File: 画像をはじめとしたファイルのアップロード処理等
  • Parse.Promise: Defferedの仕組み
  • Parse.GeoPoint: 位置情報

Parse.User

Parse.Userは、ユーザーアカウントの管理に特化したオブジェクトで、サインアップやログイン機能を実装することができます。Userは、前編でご紹介したParse.Objectのサブクラスであり、Objectのすべての機能が使えます。Objectと同じように、情報はParseに自動的に永続化されます。Objectと異なる点として、User管理に必要な以下のプロパティを保持します。

  • username(必須)
  • password(必須)
  • email(任意)

■サインアップ

新規ユーザーの作成には、signUpメソッドを使います。サインアップ時には、ユーザー名およびe-mailが一意であるかどうかチェックされ、一意でない場合にはエラーが発生します。また、パスワードはハッシュ化されますので、平文で保存されることはありません。

// 実装時はuserName、passwordをログインフォームから取得
var userName = "hiromitsuuuuu";
var password = "xxxxx";

Parse.User.signUp(userName, password, {
    success: function(user){
        // サインアップ成功
    },
    error: function(user, error){
        // サインアップ失敗
    }
});

emailをユーザー名として使ったり、パスワードのリセット機能を追加することもできます。

■ログイン

ログイン処理にはlogInメソッドを、ユーザーのログイン有無の確認にはcurrentメソッドを使います。一度ログインするとUserオブジェクトがlocalStrageにキャッシュされ、ログイン有無の判別に使われます。このキャッシュはログアウトすると消去されます。

// ログイン処理
Parse.User.logIn(userName, password, {
    success: function(user){
        // ログイン成功
    },
    error: function(user, error){
        // ログイン失敗
    }
});

// ログイン有無の確認(Boolean値が返ります)
if(Parse.User.current()){
    // ログイン済
}else{
    // 未ログイン
}

// ログアウト
Parse.User.logOut();

Userは、logInやsignUpといった認証の結果として得られたオブジェクトでなければsaveもdeleteもできない仕組みになっています。そのため、User一覧を取得したとしても他のユーザーは読み取り専用となり改編できません。Parse.User.current() は認証済みオブジェクトが返されます。

Parse.File

画像やファイルのデータはParse.Objectに収めるには大きすぎるため、これらを扱うためのParse.Fileというオブジェクトが用意されています。ドキュメントやビデオ、音声など最大10MBまでのバイナリデータを保存することができます。自力でファイルアップロードを実装する場合、multipart/form-dataエンコードが必要であったりしますが、Fileではエンコードの処理を書く必要がありません。base64形式のデータを引数として渡し、saveすればアップロードが完了します。

<input type="file" id="profile-photo">
var fileUploadControl = $("#profile-photo")[0];
if (fileUploadControl.files.length > 0) {
  var file = fileUploadControl.files[0];
  // 新規Fileオブジェクトの作成
  var parseFile = new Parse.File(file.name, file);
  // Parseへのデータ保存
  parseFile.save();
}

Fileを含む任意のObjectを作成したい場合、先に画像の保存が完了している必要があります。そのため、以下のような段階的な処理が必要となります。

  // Parseへのファイル保存
  parseFile.save({
    success: function(file){
        // articleというObject(Model)のprofilePhotoフィールドに画像を保存する
        article.set("profilePhoto", file);
        article.save();
    },
    error: function(error){
        // ファイル保存失敗
    }
  });

このように、Parseでは非同期処理を段階的に行うことが多いため、SDKでParse.Promiseというオブジェクトが用意されています。

Parse.Promise

jQueryと同様に、ParseのJavaScript SDKの非同期メソッドはPromiseを返すよう設計されています。Backboneのシンタックスと共通のObjectのsaveや、先ほどご紹介したFileのsave、前編でご紹介したQueryのfindがこれにあたります。そのため、thenメソッドを使ってメソッドチェインさせることができます。thenはコールバックのペアを引数に取り、第1引数に成功時の関数、第2引数に失敗時の関数を指定します。

obj.save().then(saveSuccess, saveFailed);
// 別途saveSuccess, saveFailed関数を定義

// チェインさせる。第1引数はすべてPromiseを返すメソッド
obj.find().then(setAttribute)
          .then(findStudents)
          .then(setStudent, setStudentErrorHandler)
          .then(sayHello, errorHandler);

whenメソッドも提供されているので、並列処理を行うこともできます。

query.find().then(function(results) {

  var promises = [];

  _.each(results, function(result) {
    // 同時に非同期処理を実行
    promises.push(result.destroy());
  });

  // すべてのPromiseが解決済みになるのを待つ
  return Parse.Promise.when(promises);
 
}).then(function() {
   // すべての処理が完了してから実行される
});

独自の非同期メソッドを作成することもできます。

function delay(time) {
  // Promiseの生成
  var promise = new Parse.Promise();
  setTimeout(function() {
    // Promiseを解決状態にする
    promise.resolve();
  }, time);
  return promise;
};
 
delay(500).then(function() {
  // 500ms後に実行される
});

このように、Promiseを利用すればコールバックでネストが深くなりがちなソースコードを見通し良く保つことができます。

Parse.GeoPoint

Parse.GeoPointは、位置情報に特化したオブジェクトです。緯度および経度を保存するために使用しますが、Queryの検索条件として指定すれば近接するユーザーや場所を特定することもできます。

// GeoPointの生成
var groPoint = new Parse.GeoPoint({latitude: 35.626446, longitude: 139.72344399999997});

// Objectのプロパティとして位置情報を保存する
placeObject.set("location", groPoint);
placeObject.save();
// 検索条件に使いたい位置情報
//(例:ユーザーの位置情報。userObjectも位置情報をプロパティに持つ場合)
var userGeoPoint = userObject.get("location");

// Queryの生成
var query = new Parse.Query(PlaceObject);

// 検索条件に指定した位置情報に近い位置情報を持っているオブジェクト
//(ここではPlaceObject)を検索する
query.near("location", userGeoPoint);
query.find();

まとめ

 後編では、ParseのJavaScript SDKの機能として、User、File、Promise、GeoPointの4つをご紹介しました。ユーザー管理やファイルアップロード、近接した位置情報の検索など、ParseとParseのSDKを使うことでアプリケーション開発で面倒となる処理を簡単に実装することができます。

 さらに詳しく知りたい方はJavaScriptガイドJS API リファレンスをご覧ください。SDKのAPIの使用方法は複雑ではありませんが、アプリケーションの作成にはBackboneやPromiseの知識が必要となるので、別途学習しておくと開発がスムーズです。