Dion Almaer dan Pamela Fox, Google
Juni 2007
Catatan Editor: Google Gears API tidak lagi tersedia.
- Pengantar
- Memahami Aplikasi
- Menggunakan Feed API data Google Base
- Menambahkan Google Gears ke Aplikasi
- Men-debug Aplikasi Offline
- Kesimpulan
Pengantar
Dengan menggabungkan Google Base dan Google Gears, kami menunjukkan cara membuat aplikasi yang dapat digunakan secara offline. Setelah membaca artikel ini, Anda akan lebih memahami Google Base API, serta memahami cara menggunakan Google Gears untuk menyimpan dan mengakses preferensi dan data pengguna.
Memahami Aplikasi
Untuk memahami aplikasi ini, Anda harus terlebih dahulu memahami Google Base, yang pada dasarnya adalah database besar item yang mencakup berbagai kategori seperti produk, ulasan, resep, acara, dan lainnya.
Setiap item diberi anotasi dengan judul, deskripsi, link ke sumber asli data (jika ada), serta atribut tambahan yang bervariasi per jenis kategori. Google Base memanfaatkan fakta bahwa item dalam kategori yang sama memiliki serangkaian atribut yang sama—misalnya, semua resep memiliki bahan-bahan. Item Google Base bahkan terkadang muncul di hasil penelusuran dari penelusuran web Google atau penelusuran produk Google.
Aplikasi demo kami, Base with Gears, memungkinkan Anda menyimpan dan menampilkan penelusuran umum yang mungkin Anda lakukan di Google Base, seperti menemukan resep dengan "cokelat" (enak) atau iklan pribadi dengan "berjalan di pantai" (romantis!). Anda dapat menganggapnya sebagai "Pembaca Google Base" yang memungkinkan Anda berlangganan penelusuran dan melihat hasil yang diperbarui saat Anda membuka kembali aplikasi, atau saat aplikasi mencari feed yang diperbarui setiap 15 menit.
Developer yang ingin memperluas aplikasi dapat menambahkan lebih banyak fitur, seperti memberi tahu pengguna secara visual saat hasil penelusuran berisi hasil baru, memungkinkan pengguna menandai (membintangi) item favorit (offline + online), dan memungkinkan pengguna melakukan penelusuran atribut khusus kategori seperti Google Base.
Menggunakan Feed API data Google Base
Google Base dapat dikueri secara terprogram dengan Google Base Data API, yang sesuai dengan framework Google Data API. Protokol Google Data API menyediakan protokol sederhana untuk membaca dan menulis di web, dan digunakan oleh banyak produk Google: Picasa, Spreadsheet, Blogger, Kalender, Notebook, dan lainnya.
Format Google Data API didasarkan pada XML dan Atom Publishing Protocol, sehingga sebagian besar interaksi baca/tulis menggunakan XML.
Contoh feed Google Base berdasarkan Google Data API adalah:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera
Jenis feed snippets
memberi kita feed item yang tersedia secara publik. -/products
memungkinkan kita membatasi feed ke kategori produk. Selain itu, parameter bq=
memungkinkan kita membatasi feed lebih lanjut, hanya untuk hasil yang berisi kata kunci "kamera digital". Jika melihat feed ini di browser, Anda akan melihat XML yang berisi node <entry>
dengan hasil yang cocok. Setiap entri berisi elemen penulis, judul, konten, dan link yang umum, tetapi juga dilengkapi dengan atribut tambahan khusus kategori (seperti "harga" untuk item dalam kategori produk).
Karena batasan lintas domain XMLHttpRequest di browser, kita tidak diizinkan untuk membaca feed XML secara langsung dari www.google.com dalam kode JavaScript kita. Kita dapat menyiapkan proxy sisi server untuk membaca XML dan mengirimkannya kembali di lokasi pada domain yang sama dengan aplikasi kita, tetapi kita ingin menghindari pemrograman sisi server sepenuhnya. Untungnya, ada alternatif.
Seperti Google Data API lainnya, Google Base Data API memiliki opsi output JSON, selain XML standar. Output untuk feed yang kita lihat sebelumnya dalam format JSON akan berada di URL ini:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera&alt=json
JSON adalah format pertukaran ringan yang memungkinkan penyusunan hierarkis serta berbagai jenis data. Namun yang lebih penting, output JSON adalah kode JavaScript itu sendiri, sehingga dapat dimuat ke halaman web Anda hanya dengan mereferensikannya dalam tag skrip, sehingga melewati batasan lintas domain.
Google Data API juga memungkinkan Anda menentukan output "json-in-script" dengan fungsi callback yang akan dijalankan setelah JSON dimuat. Hal ini membuat output JSON lebih mudah digunakan, karena kita dapat menambahkan tag skrip ke halaman secara dinamis dan menentukan fungsi callback yang berbeda untuk setiap tag.
Jadi, untuk memuat feed JSON Base API secara dinamis ke dalam halaman, kita dapat menggunakan fungsi berikut yang membuat tag skrip dengan URL feed (ditambahkan dengan nilai alt
callback
) dan menambahkannya ke halaman.
function getJSON() { var script = document.createElement('script'); var url = "http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera"; script.setAttribute('src', url + "&alt=json-in-script&callback=listResults"); script.setAttribute('type', 'text/JavaScript'); document.documentElement.firstChild.appendChild(script); }
Jadi, fungsi callback listResults
kini dapat melakukan iterasi melalui JSON yang diteruskan sebagai satu-satunya parameter dan menampilkan informasi tentang setiap entri yang ditemukan dalam daftar berbutir.
function listTasks(root) { var feed = root.feed; var html = ['']; html.push('<ul>'); for (var i = 0; i < feed.entry.length; ++i) { var entry = feed.entry[i]; var title = entry.title.$t; var content = entry.content.$t; html.push('<li>', title, ' (', content, ')</li>'); } html.push('</ul>'); document.getElementById("agenda").innerHTML = html.join(""); }
Menambahkan Google Gears
Sekarang setelah memiliki aplikasi yang dapat berkomunikasi dengan Google Base melalui Google Data API, kita ingin mengaktifkan aplikasi ini agar dapat berjalan secara offline. Di sinilah Google Gears berperan.
Ada berbagai pilihan arsitektur saat menulis aplikasi yang dapat digunakan secara offline. Anda akan mengajukan pertanyaan tentang cara kerja aplikasi secara online vs. offline (misalnya, Apakah cara kerjanya sama persis? Apakah beberapa fitur dinonaktifkan, seperti penelusuran? Bagaimana Anda akan menangani sinkronisasi?)
Dalam kasus kami, kami ingin memastikan bahwa pengguna di browser tanpa Gears tetap dapat menggunakan aplikasi, sekaligus memberikan manfaat penggunaan offline dan UI yang lebih responsif kepada pengguna yang memiliki plug-in.
Arsitektur kita terlihat seperti ini:
- Kita memiliki objek JavaScript yang bertugas menyimpan kueri penelusuran Anda dan menampilkan kembali hasil dari kueri ini.
- Jika Anda telah menginstal Google Gears, Anda akan mendapatkan versi Gears yang menyimpan semuanya dalam database lokal.
- Jika Anda tidak menginstal Google Gears, Anda akan mendapatkan versi yang menyimpan kueri dalam cookie dan tidak menyimpan hasil lengkap sama sekali (sehingga responsnya sedikit lebih lambat), karena hasilnya terlalu besar untuk disimpan dalam cookie.
if (online) {}
di seluruh toko. Sebagai gantinya, aplikasi memiliki satu pemeriksaan Gears, lalu adaptor yang benar digunakan.
Menggunakan Database Lokal Gears
Salah satu komponen Gears adalah database SQLite lokal yang disematkan dan siap Anda gunakan. Ada API database sederhana yang akan terlihat familiar bagi Anda jika sebelumnya Anda telah menggunakan API untuk database sisi server seperti MySQL atau Oracle.
Langkah-langkah untuk menggunakan database lokal cukup sederhana:
- Menginisialisasi objek Google Gears
- Mendapatkan objek factory database, dan membuka database
- Mulai mengeksekusi permintaan SQL
Mari kita bahas secara singkat.
Lakukan Inisialisasi Objek Google Gears
Aplikasi Anda harus membaca konten /gears/samples/gears_init.js
secara langsung, atau dengan menempelkan kode ke file JavaScript Anda sendiri. Setelah <script src="..../gears_init.js" type="text/JavaScript"></script>
berjalan, Anda memiliki akses ke namespace google.gears.
Mendapatkan Objek Database Factory & Membuka Database
var db = google.gears.factory.create('beta.database', '1.0'); db.open('testdb');
Satu panggilan ini akan memberi Anda objek database yang memungkinkan Anda membuka skema database. Saat Anda membuka database, database tersebut akan diberi cakupan melalui aturan kebijakan origin yang sama, sehingga "testdb" Anda tidak akan berbenturan dengan "testdb" saya.
Mulai Mengeksekusi Permintaan SQL
Sekarang kita siap mengirim permintaan SQL ke database. Saat mengirim permintaan "select", kita akan mendapatkan kembali kumpulan hasil yang dapat diulang untuk data yang diinginkan:
var rs = db.execute('select * from foo where name = ?', [ name ]);
Anda dapat mengoperasikan set hasil yang ditampilkan dengan metode berikut:
boolean | isValidRow() |
void | next() |
void | close() |
int | fieldCount() |
string | fieldName(int fieldIndex) |
variant | field(int fieldIndex) |
variant | fieldByName(string fieldname) |
Untuk mengetahui detail selengkapnya, lihat dokumentasi Database Module API. (Catatan Editor: Google Gears API tidak lagi tersedia).
Menggunakan GearsDB untuk Mengenkapsulasi API Tingkat Rendah
Kami ingin merangkum dan mempermudah beberapa tugas database umum. Misalnya,
- Kami ingin memiliki cara yang bagus untuk mencatat SQL yang dihasilkan saat kami men-debug aplikasi.
- Kita ingin menangani pengecualian di satu tempat, bukan harus melakukan
try{}catch(){}
di mana-mana. - Kita ingin menangani objek JavaScript, bukan set hasil saat membaca atau menulis data.
Untuk menangani masalah ini secara umum, kami membuat GearsDB, library open source yang membungkus objek Database. Sekarang kita akan menunjukkan cara menggunakan GearsDB.
Penyiapan Awal
Dalam kode window.onload, kita harus memastikan bahwa tabel database yang kita andalkan sudah ada. Jika pengguna telah menginstal Gears saat kode berikut berjalan, mereka akan membuat objek GearsBaseContent
:
content = hasGears() ? new GearsBaseContent() : new CookieBaseContent();
Selanjutnya, kita membuka database dan membuat tabel jika belum ada:
db = new GearsDB('gears-base'); // db is defined as a global for reuse later! if (db) { db.run('create table if not exists BaseQueries' + ' (Phrase varchar(255), Itemtype varchar(100))'); db.run('create table if not exists BaseFeeds' + ' (id varchar(255), JSON text)'); }
Pada tahap ini, kita yakin bahwa kita memiliki tabel untuk menyimpan kueri dan feed. Kode new GearsDB(name)
akan merangkum pembukaan database dengan nama yang diberikan. Metode run
membungkus metode execute
tingkat bawah, tetapi juga menangani output proses debug ke konsol dan menjebak pengecualian.
Menambahkan Istilah Penelusuran
Saat pertama kali menjalankan aplikasi, Anda tidak akan memiliki penelusuran apa pun. Jika Anda mencoba menelusuri Nintendo Wii di produk, kami akan menyimpan istilah penelusuran ini di tabel BaseQueries.
Versi Gears dari metode addQuery
melakukannya dengan mengambil input dan menyimpannya melalui insertRow
:
var searchterm = { Phrase: phrase, Itemtype: itemtype }; db.insertRow('BaseQueries', searchterm);
insertRow
mengambil objek JavaScript (searchterm
) dan menangani penyisipannya ke dalam tabel untuk Anda. Anda juga dapat menentukan batasan (misalnya, penyisipan blok keunikan lebih dari satu "Bob"). Namun, sebagian besar waktu Anda akan menangani batasan ini di database itu sendiri.
Mendapatkan Semua Istilah Penelusuran
Untuk mengisi daftar penelusuran sebelumnya, kita menggunakan wrapper pilihan yang bagus bernama selectAll
:
GearsBaseContent.prototype.getQueries = function() { return this.db.selectAll('select * from BaseQueries'); }
Tindakan ini akan menampilkan array objek JavaScript yang cocok dengan baris dalam database (misalnya, [ { Phrase: 'Nintendo Wii', Itemtype: 'product' }, { ... }, ...]
).
Dalam hal ini, Anda dapat menampilkan daftar lengkap. Namun, jika memiliki banyak data, Anda mungkin ingin menggunakan callback dalam panggilan select sehingga Anda dapat mengoperasikan setiap baris yang ditampilkan saat masuk:
db.selectAll('select * from BaseQueries where Itemtype = ?', ['product'], function(row) { ... do something with this row ... });
Berikut beberapa metode pemilihan berguna lainnya di GearsDB:
selectOne(sql, args) | Menampilkan objek JavaScript pertama/satu yang cocok |
selectRow(table, where, args, select) | Biasanya digunakan dalam kasus sederhana untuk mengabaikan SQL |
selectRows(table, where, args, callback, select) | Sama seperti selectRow, tetapi untuk beberapa hasil. |
Memuat Feed
Saat mendapatkan feed hasil dari Google Base, kita perlu menyimpannya ke database:
content.setFeed({ id: id, JSON: json.toJSONString() }); ... which calls ... GearsBaseContent.prototype.setFeed = function(feed) { this.db.forceRow('BaseFeeds', feed); }
Pertama-tama, kita mengambil feed JSON dan menampilkannya sebagai String menggunakan metode toJSONString
. Kemudian, kita membuat objek feed
dan meneruskannya ke metode forceRow
. forceRow
akan MEMASUKKAN entri jika belum ada, atau MEMPERBARUI entri yang ada.
Menampilkan Hasil Penelusuran
Aplikasi kami menampilkan hasil untuk penelusuran tertentu di panel kanan halaman. Berikut cara kami mengambil feed yang terkait dengan istilah penelusuran:
GearsBaseContent.prototype.getFeed = function(url) { var row = this.db.selectRow('BaseFeeds', 'id = ?', [ url ]); return row.JSON; }
Setelah memiliki JSON untuk baris, kita dapat eval()
untuk mendapatkan kembali objek:
eval("var json = " + jsonString + ";");
Kita sudah siap dan dapat mulai menggunakan innerHTML untuk memasukkan konten dari JSON ke halaman kita.
Menggunakan Penyimpanan Resource untuk Akses Offline
Karena kita mendapatkan konten dari database lokal, aplikasi ini juga harus berfungsi secara offline, bukan?
Tidak. Masalahnya adalah untuk memulai aplikasi ini, Anda perlu memuat resource web-nya, seperti JavaScript, CSS, HTML, dan gambar. Saat ini, jika pengguna Anda melakukan langkah-langkah berikut, aplikasi mungkin masih berfungsi: mulai online, lakukan beberapa penelusuran, jangan tutup browser, beralih offline. Cara ini dapat berhasil karena item masih berada di cache browser. Namun, bagaimana jika tidak demikian? Kita ingin pengguna dapat mengakses aplikasi dari awal, setelah melakukan booting ulang, dll.
Untuk melakukannya, kita menggunakan komponen LocalServer dan mengambil resource. Saat Anda mengambil resource (seperti HTML dan JavaScript yang diperlukan untuk menjalankan aplikasi), Gears akan menyimpan item ini dan juga akan menjebak permintaan dari browser untuk mengembalikannya. Server lokal akan bertindak sebagai pengatur traffic dan menampilkan konten yang disimpan dari penyimpanan.
Kami juga menggunakan komponen ResourceStore, yang mengharuskan Anda memberi tahu sistem secara manual file mana yang ingin Anda ambil. Dalam banyak skenario, Anda ingin membuat versi aplikasi dan mengizinkan upgrade secara transaksional. Kumpulan resource bersama-sama menentukan versi, dan saat merilis kumpulan resource baru, Anda ingin pengguna mengupgrade file dengan lancar. Jika itu adalah model Anda, Anda akan menggunakan ManagedResourceStore API.
Untuk mengambil resource kita, objek GearsBaseContent akan:
- Siapkan array file yang perlu direkam
- Membuat LocalServer
- Membuka atau membuat ResourceStore baru
- Panggil untuk mengambil halaman ke dalam toko
// Step 1 this.storeName = 'gears-base'; this.pageFiles = [ location.pathname, 'gears_base.js', '../scripts/gears_db.js', '../scripts/firebug/firebug.js', '../scripts/firebug/firebug.html', '../scripts/firebug/firebug.css', '../scripts/json_util.js', 'style.css', 'capture.gif' ]; // Step 2 try { this.localServer = google.gears.factory.create('beta.localserver', '1.0'); } catch (e) { alert('Could not create local server: ' + e.message); return; } // Step 3 this.store = this.localServer.openStore(this.storeName) || this.localServer.createStore(this.storeName); // Step 4 this.capturePageFiles(); ... which calls ... GearsBaseContent.prototype.capturePageFiles = function() { this.store.capture(this.pageFiles, function(url, success, captureId) { console.log(url + ' capture ' + (success ? 'succeeded' : 'failed')); }); }
Yang penting untuk diperhatikan di sini adalah Anda hanya dapat merekam resource di domain Anda sendiri. Kami mengalami batasan ini saat mencoba mengakses file JavaScript GearsDB secara langsung dari file "gears_db.js" asli di trunk SVN-nya. Tentu saja, solusinya sederhana: Anda perlu mendownload semua resource eksternal dan menempatkannya di domain Anda. Perhatikan bahwa pengalihan 302 atau 301 tidak akan berfungsi, karena LocalServer hanya menerima kode server 200 (Berhasil) atau 304 (Tidak Diubah).
Hal ini memiliki implikasi. Jika Anda menempatkan gambar di images.yourdomain.com, Anda tidak akan dapat mengambilnya. www1 dan www2 tidak dapat melihat satu sama lain. Anda dapat menyiapkan proxy sisi server, tetapi hal itu akan menghilangkan tujuan memisahkan aplikasi ke beberapa domain.
Men-debug Aplikasi Offline
Proses men-debug aplikasi offline sedikit lebih rumit. Sekarang ada lebih banyak skenario yang perlu diuji:
- Saya online dengan aplikasi yang berjalan sepenuhnya di cache
- Saya sedang online, tetapi belum mengakses aplikasi, dan tidak ada yang ada di cache
- Saya sedang offline, tetapi telah mengakses aplikasi
- Saya sedang offline dan belum pernah mengakses aplikasi (bukan tempat yang baik untuk berada!)
Untuk mempermudah, kami menggunakan pola berikut:
- Kami menonaktifkan cache di Firefox (atau browser pilihan Anda) saat kami perlu memastikan bahwa browser tidak hanya mengambil sesuatu dari cache
- Kita men-debug menggunakan Firebug (dan Firebug Lite untuk pengujian di browser lain); kita menggunakan
console.log()
di mana-mana, dan mendeteksi konsol untuk berjaga-jaga - Kita menambahkan kode JavaScript helper ke:
- memungkinkan kita menghapus database dan memulai dari awal
- menghapus file yang diambil, sehingga saat Anda memuat ulang, file tersebut akan diambil lagi dari Internet (berguna saat Anda melakukan iterasi pada pengembangan ;)
Widget debug muncul di sisi kiri halaman hanya jika Anda telah menginstal Gears. Memiliki anotasi untuk membersihkan kode:
GearsBaseContent.prototype.clearServer = function() { if (this.localServer.openStore(this.storeName)) { this.localServer.removeStore(this.storeName); this.store = null; } } GearsBaseContent.prototype.clearTables = function() { if (this.db) { this.db.run('delete from BaseQueries'); this.db.run('delete from BaseFeeds'); } displayQueries(); }
Kesimpulan
Anda dapat melihat bahwa bekerja dengan Google Gears sebenarnya cukup sederhana. Kami menggunakan GearsDB untuk mempermudah komponen Database, dan menggunakan ResourceStore manual, yang berfungsi dengan baik untuk contoh kami.
Area tempat Anda menghabiskan sebagian besar waktu menentukan strategi kapan mendapatkan data secara online, dan cara menyimpannya secara offline. Penting untuk meluangkan waktu dalam menentukan skema database. Jika Anda perlu mengubah skema di masa mendatang, Anda harus mengelola perubahan tersebut karena pengguna saat ini sudah memiliki versi database. Artinya, Anda harus mengirimkan kode skrip dengan upgrade db apa pun. Tentu saja, hal ini membantu meminimalkan masalah tersebut, dan Anda dapat mencoba GearShift, sebuah library kecil yang dapat membantu Anda mengelola revisi.
Kita juga dapat menggunakan ManagedResourceStore untuk melacak file, dengan konsekuensi berikut:
- Kita akan menjadi warga negara yang baik dan membuat versi file untuk memungkinkan upgrade bersih di masa mendatang
- Ada fitur ManagedResourceStore yang memungkinkan Anda membuat alias URL ke konten lain. Pilihan arsitektur yang valid adalah membuat gears_base.js menjadi versi non-Gears, dan membuat alias sehingga Gears sendiri akan mendownload gears_base_withgears.js yang akan memiliki semua dukungan offline.
Semoga Anda merasa persiapan aplikasi menyenangkan dan mudah. Bergabunglah dengan kami di forum Google Gears jika ada pertanyaan atau aplikasi yang ingin Anda bagikan.