बेहतर परफ़ॉर्मेंस और ऑफ़लाइन अनुभव के लिए, Google Base और Google Gears का इस्तेमाल करना

"Google API की मदद से बेहतर Ajax ऐप्लिकेशन बनाना" सीरीज़ का पहला लेख.

डियन अल्मेर और पामेला फ़ॉक्स, Google
जून 2007

संपादक का नोट: Google Gears API अब उपलब्ध नहीं है.

परिचय

Google Base और Google Gears को मिलाकर, हमने एक ऐसा ऐप्लिकेशन बनाने का तरीका बताया है जिसका इस्तेमाल ऑफ़लाइन किया जा सकता है. इस लेख को पढ़ने के बाद, आपको Google Base API के बारे में ज़्यादा जानकारी मिल जाएगी. साथ ही, आपको यह भी पता चल जाएगा कि उपयोगकर्ता की प्राथमिकताओं और डेटा को सेव करने और ऐक्सेस करने के लिए, Google Gears का इस्तेमाल कैसे किया जाता है.

ऐप्लिकेशन के बारे में जानकारी

इस ऐप्लिकेशन को समझने के लिए, आपको सबसे पहले Google Base के बारे में पता होना चाहिए. यह अलग-अलग कैटगरी के आइटम का एक बड़ा डेटाबेस है. जैसे, प्रॉडक्ट, समीक्षाएं, रेसिपी, इवेंट वगैरह.

हर आइटम को एनोटेट किया जाता है. इसमें टाइटल, ब्यौरा, डेटा के मूल सोर्स का लिंक (अगर मौजूद है) के साथ-साथ अन्य एट्रिब्यूट शामिल होते हैं. ये एट्रिब्यूट, कैटगरी के टाइप के हिसाब से अलग-अलग होते हैं. Google Base इस बात का फ़ायदा उठाता है कि एक ही कैटगरी के आइटम में एट्रिब्यूट का एक जैसा सेट होता है. उदाहरण के लिए, सभी रेसिपी में सामग्री होती है. Google Base में मौजूद आइटम, कभी-कभी Google वेब सर्च या Google प्रॉडक्ट सर्च के खोज नतीजों में भी दिखते हैं.

हमारे डेमो ऐप्लिकेशन, Base with Gears की मदद से, Google Base पर की जाने वाली सामान्य खोजों को सेव और दिखाया जा सकता है. जैसे, "चॉकलेट" (स्वादिष्ट) के साथ रेसिपी खोजना या "समुद्र के किनारे घूमना" (रोमांटिक!) के साथ निजी विज्ञापन खोजना. इसे "Google Base Reader" के तौर पर देखा जा सकता है. इसकी मदद से, खोजों की सदस्यता ली जा सकती है. साथ ही, ऐप्लिकेशन को फिर से खोलने पर अपडेट किए गए नतीजे देखे जा सकते हैं. इसके अलावा, हर 15 मिनट में ऐप्लिकेशन अपडेट किए गए फ़ीड की जानकारी खोजता है.

ऐप्लिकेशन को बेहतर बनाने के लिए डेवलपर, कई सुविधाएं जोड़ सकते हैं. जैसे, खोज के नतीजों में नए नतीजे दिखने पर उपयोगकर्ता को विज़ुअल अलर्ट दिखाना, उपयोगकर्ता को पसंदीदा आइटम (ऑफ़लाइन + ऑनलाइन) बुकमार्क (स्टार) करने की सुविधा देना, और उपयोगकर्ता को Google Base की तरह कैटगरी के हिसाब से एट्रिब्यूट खोजने की सुविधा देना.

Google Base data API फ़ीड का इस्तेमाल करना

Google Base के डेटा को प्रोग्राम के हिसाब से, Google Base data API की मदद से क्वेरी किया जा सकता है. यह Google Data API फ़्रेमवर्क के मुताबिक काम करता है. Google Data API प्रोटोकॉल, वेब पर पढ़ने और लिखने के लिए एक आसान प्रोटोकॉल उपलब्ध कराता है. इसका इस्तेमाल Google के कई प्रॉडक्ट करते हैं: Picasa, Spreadsheets, Blogger, Calendar, Notebook वगैरह.

Google Data API का फ़ॉर्मैट, एक्सएमएल और ऐटम पब्लिशिंग प्रोटोकॉल पर आधारित है. इसलिए, पढ़ने/लिखने से जुड़ी ज़्यादातर इंटरैक्शन एक्सएमएल में होती हैं.

Google Data API पर आधारित Google Base फ़ीड का उदाहरण यहां दिया गया है:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera

snippets फ़ीड टाइप से हमें आइटम का सार्वजनिक तौर पर उपलब्ध फ़ीड मिलता है. -/products की मदद से, हम फ़ीड को प्रॉडक्ट कैटगरी तक सीमित कर सकते हैं. साथ ही, bq= पैरामीटर की मदद से, हम फ़ीड को और भी ज़्यादा सीमित कर सकते हैं. इससे हमें सिर्फ़ "डिजिटल कैमरा" कीवर्ड वाले नतीजे दिखेंगे. इस फ़ीड को ब्राउज़र में देखने पर, आपको <entry> नोड वाला एक्सएमएल दिखेगा. इसमें मिलते-जुलते नतीजे होंगे. हर एंट्री में लेखक, टाइटल, कॉन्टेंट, और लिंक के एलिमेंट शामिल होते हैं. हालांकि, इसमें कैटगरी के हिसाब से अतिरिक्त एट्रिब्यूट भी शामिल होते हैं. जैसे, प्रॉडक्ट कैटगरी में मौजूद आइटम के लिए "कीमत" एट्रिब्यूट.

ब्राउज़र में XMLHttpRequest पर क्रॉस-डोमेन की पाबंदी की वजह से, हमें अपने JavaScript कोड में www.google.com से सीधे तौर पर एक्सएमएल फ़ीड पढ़ने की अनुमति नहीं है. हम एक्सएमएल को पढ़ने और उसे अपने ऐप्लिकेशन के डोमेन पर किसी जगह पर वापस भेजने के लिए, सर्वर-साइड प्रॉक्सी सेट अप कर सकते हैं. हालांकि, हम सर्वर-साइड प्रोग्रामिंग से पूरी तरह बचना चाहते हैं. हालांकि, इसका एक विकल्प उपलब्ध है.

Google के अन्य डेटा एपीआई की तरह, Google Base डेटा एपीआई में भी स्टैंडर्ड XML के अलावा JSON आउटपुट का विकल्प होता है. हमने फ़ीड का जो आउटपुट JSON फ़ॉर्मैट में देखा था वह इस यूआरएल पर होगा:
http://www.google.com/base/feeds/snippets/-/products?bq=digital+camera&alt=json

JSON, डेटा सेव और ट्रांसमिट करने का आसान फ़ॉर्मैट है. इसमें डेटा को क्रम के हिसाब से व्यवस्थित किया जा सकता है. साथ ही, इसमें अलग-अलग तरह के डेटा को सेव किया जा सकता है. हालांकि, इससे भी ज़्यादा ज़रूरी बात यह है कि JSON आउटपुट, नेटिव JavaScript कोड होता है. इसलिए, इसे अपने वेब पेज में सिर्फ़ स्क्रिप्ट टैग में रेफ़रंस देकर लोड किया जा सकता है. इससे क्रॉस-डोमेन की पाबंदी को अनदेखा किया जा सकता है.

Google Data APIs की मदद से, "json-in-script" आउटपुट भी तय किया जा सकता है. इसमें एक कॉलबैक फ़ंक्शन होता है, जो JSON लोड होने के बाद काम करता है. इससे JSON आउटपुट के साथ काम करना और भी आसान हो जाता है. ऐसा इसलिए, क्योंकि हम पेज में स्क्रिप्ट टैग को डाइनैमिक तौर पर जोड़ सकते हैं और हर टैग के लिए अलग-अलग कॉलबैक फ़ंक्शन तय कर सकते हैं.

इसलिए, पेज में Base API JSON फ़ीड को डाइनैमिक तौर पर लोड करने के लिए, हम इस फ़ंक्शन का इस्तेमाल कर सकते हैं. यह फ़ंक्शन, फ़ीड यूआरएल (altcallback वैल्यू के साथ जोड़ा गया) के साथ एक स्क्रिप्ट टैग बनाता है और उसे पेज में जोड़ता है.

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);
}

इसलिए, हमारा कॉलबैक फ़ंक्शन listResults अब सिर्फ़ एक पैरामीटर के तौर पर पास किए गए JSON को दोहरा सकता है. साथ ही, बुलेट वाली सूची में मिली हर एंट्री की जानकारी दिखा सकता है.

  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("");
  }

Google Gears जोड़ना

अब हमारे पास एक ऐसा ऐप्लिकेशन है जो Google Data API के ज़रिए Google Base से कम्यूनिकेट कर सकता है. अब हमें इस ऐप्लिकेशन को ऑफ़लाइन चलाने की सुविधा चालू करनी है. ऐसे में, Google Gears आपकी मदद करता है.

ऐसे ऐप्लिकेशन को ऑफ़लाइन इस्तेमाल करने की सुविधा देने के लिए, कई तरह के आर्किटेक्चर का इस्तेमाल किया जा सकता है. आपको खुद से यह सवाल पूछने होंगे कि ऐप्लिकेशन को ऑनलाइन और ऑफ़लाइन कैसे काम करना चाहिए. उदाहरण के लिए, क्या यह दोनों मोड में एक जैसा काम करता है? क्या खोज जैसी कुछ सुविधाएं बंद हैं? सिंक करने की सुविधा को कैसे मैनेज किया जाएगा?)

हमारे मामले में, हम यह पक्का करना चाहते थे कि Gears के बिना ब्राउज़र इस्तेमाल करने वाले लोग भी ऐप्लिकेशन का इस्तेमाल कर सकें. साथ ही, जिन लोगों के पास प्लग-इन है उन्हें ऑफ़लाइन इस्तेमाल करने की सुविधा और ज़्यादा रिस्पॉन्सिव यूज़र इंटरफ़ेस (यूआई) मिल सके.

हमारा आर्किटेक्चर ऐसा दिखता है:

  • हमारे पास एक JavaScript ऑब्जेक्ट है. यह आपकी खोज क्वेरी को सेव करने और इन क्वेरी से नतीजे वापस लाने का काम करता है.
  • अगर आपने Google Gears इंस्टॉल किया है, तो आपको Gears का ऐसा वर्शन मिलता है जो सभी डेटा को लोकल डेटाबेस में सेव करता है.
  • अगर आपने Google Gears इंस्टॉल नहीं किया है, तो आपको ऐसा वर्शन मिलता है जो कुकी में क्वेरी सेव करता है और पूरे नतीजे सेव नहीं करता. इसलिए, यह थोड़ा धीरे काम करता है, क्योंकि नतीजे इतने बड़े होते हैं कि उन्हें कुकी में सेव नहीं किया जा सकता.
इस आर्किटेक्चर की सबसे अच्छी बात यह है कि आपको if (online) {} के लिए पूरी दुकान में जांच करने की ज़रूरत नहीं है. इसके बजाय, ऐप्लिकेशन में एक Gears चेक होता है. इसके बाद, सही अडैप्टर का इस्तेमाल किया जाता है.


Gears के लोकल डेटाबेस का इस्तेमाल करना

Gears के कॉम्पोनेंट में से एक, लोकल SQLite डेटाबेस है. यह एम्बेड किया गया है और इस्तेमाल के लिए तैयार है. इसमें एक आसान डेटाबेस एपीआई होता है. अगर आपने पहले MySQL या Oracle जैसे सर्वर-साइड डेटाबेस के लिए एपीआई का इस्तेमाल किया है, तो आपको यह एपीआई जाना-पहचाना लगेगा.

लोकल डेटाबेस का इस्तेमाल करने का तरीका बहुत आसान है:

  • Google Gears ऑब्जेक्ट शुरू करना
  • डेटाबेस फ़ैक्ट्री ऑब्जेक्ट पाना और डेटाबेस खोलना
  • एसक्यूएल अनुरोधों को लागू करना शुरू करें

आइए, इनके बारे में जल्दी से जान लेते हैं.


Google Gears ऑब्जेक्ट को शुरू करना

आपका ऐप्लिकेशन, /gears/samples/gears_init.js के कॉन्टेंट को सीधे तौर पर पढ़े या कोड को अपनी JavaScript फ़ाइल में चिपकाकर पढ़े. <script src="..../gears_init.js" type="text/JavaScript"></script> चालू होने के बाद, आपके पास google.gears नेमस्पेस का ऐक्सेस होता है.


डेटाबेस फ़ैक्ट्री ऑब्जेक्ट पाना और डेटाबेस खोलना
var db = google.gears.factory.create('beta.database', '1.0');
db.open('testdb');

इस एक कॉल से आपको एक डेटाबेस ऑब्जेक्ट मिलेगा. इसकी मदद से, डेटाबेस स्कीमा खोला जा सकता है. डेटाबेस खोलने पर, उन्हें एक ही ऑरिजिन नीति के नियमों के हिसाब से स्कोप किया जाता है. इसलिए, आपका "testdb" मेरे "testdb" से अलग होगा.


एसक्यूएल अनुरोधों को लागू करना शुरू करें

अब हम डेटाबेस को एसक्यूएल अनुरोध भेजने के लिए तैयार हैं. "select" अनुरोध भेजने पर, हमें नतीजों का एक सेट मिलता है. इसमें मौजूद डेटा को हम अपनी ज़रूरत के हिसाब से इस्तेमाल कर सकते हैं:

var rs = db.execute('select * from foo where name = ?', [ name ]);

लौटाए गए नतीजों के सेट पर, इन तरीकों से कार्रवाई की जा सकती है:

booleanisValidRow()
voidnext()
voidclose()
intfieldCount()
stringfieldName(int fieldIndex)
variantfield(int fieldIndex)
variantfieldByName(string fieldname)

ज़्यादा जानकारी के लिए, कृपया डेटाबेस मॉड्यूल के एपीआई से जुड़ा दस्तावेज़ देखें. (संपादक का नोट: Google Gears API अब उपलब्ध नहीं है).


Low Level API को Encapsulate करने के लिए GearsDB का इस्तेमाल करना

हम डेटाबेस से जुड़े कुछ सामान्य कामों को आसान बनाना चाहते थे. उदाहरण के लिए,

  • हम चाहते थे कि ऐप्लिकेशन को डीबग करते समय जनरेट हुए एसक्यूएल को लॉग करने का एक अच्छा तरीका हो.
  • हम चाहते थे कि अपवादों को एक ही जगह पर हैंडल किया जाए, न कि हर जगह try{}catch(){} करना पड़े.
  • हमें डेटा को पढ़ने या लिखने के दौरान, नतीजों के सेट के बजाय JavaScript ऑब्जेक्ट का इस्तेमाल करना था.

इन समस्याओं को सामान्य तरीके से हल करने के लिए, हमने GearsDB बनाई है. यह एक ओपन सोर्स लाइब्रेरी है, जो डेटाबेस ऑब्जेक्ट को रैप करती है. अब हम GearsDB का इस्तेमाल करने का तरीका बताएंगे.

शुरुआती सेटअप

हमारे window.onload कोड में, हमें यह पक्का करना होगा कि हम जिन डेटाबेस टेबल पर भरोसा करते हैं वे मौजूद हों. अगर उपयोगकर्ता ने यह कोड चलाने के दौरान Gears इंस्टॉल किया है, तो वे GearsBaseContent ऑब्जेक्ट बनाएंगे:

content = hasGears() ? new GearsBaseContent() : new CookieBaseContent();

इसके बाद, हम डेटाबेस खोलते हैं और अगर टेबल पहले से मौजूद नहीं हैं, तो उन्हें बनाते हैं:

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)');
}

इस समय, हमें यकीन है कि हमारे पास क्वेरी और फ़ीड सेव करने के लिए एक टेबल है. कोड new GearsDB(name), दिए गए नाम के डेटाबेस को खोलने की प्रोसेस को शामिल करेगा. run तरीका, निचले लेवल के execute तरीके को रैप करता है. हालांकि, यह कंसोल में डीबग करने से जुड़े आउटपुट को भी हैंडल करता है और अपवादों को ट्रैप करता है.


खोज के लिए इस्तेमाल होने वाला शब्द जोड़ना

पहली बार ऐप्लिकेशन चलाने पर, आपको कोई खोज नहीं दिखेगी. अगर आपने प्रॉडक्ट में Nintendo Wii को खोजा, तो हम इस खोज क्वेरी को BaseQueries टेबल में सेव करेंगे.

addQuery तरीके का Gears वर्शन, इनपुट लेकर उसे insertRow के ज़रिए सेव करता है:

var searchterm = { Phrase: phrase, Itemtype: itemtype };
db.insertRow('BaseQueries', searchterm); 

insertRow एक JavaScript ऑब्जेक्ट (searchterm) लेता है और उसे टेबल में INSERT करने का काम करता है. इससे, शर्तों को भी तय किया जा सकता है. उदाहरण के लिए, एक से ज़्यादा "Bob" को शामिल करने से जुड़ी शर्त. हालांकि, ज़्यादातर समय आपको डेटाबेस में ही इन शर्तों को मैनेज करना होगा.


खोज के लिए इस्तेमाल हुए सभी शब्द पाना

पिछली खोजों की सूची को भरने के लिए, हम selectAll नाम के एक अच्छे सिलेक्ट रैपर का इस्तेमाल करते हैं:

GearsBaseContent.prototype.getQueries = function() {
  return this.db.selectAll('select * from BaseQueries');
}

इससे, डेटाबेस में मौजूद पंक्तियों से मेल खाने वाले JavaScript ऑब्जेक्ट का एक कलेक्शन मिलेगा. जैसे, [ { Phrase: 'Nintendo Wii', Itemtype: 'product' }, { ... }, ...].

इस मामले में, पूरी सूची दिखाई जा सकती है. हालांकि, अगर आपके पास बहुत ज़्यादा डेटा है, तो शायद आपको select कॉल में कॉलबैक का इस्तेमाल करना पड़े. इससे, आपको हर उस लाइन पर कार्रवाई करने का मौका मिलेगा जो वापस आती है:

 db.selectAll('select * from BaseQueries where Itemtype = ?', ['product'], function(row) {
  ... do something with this row ...
});

GearsDB में, चुनने के कुछ अन्य तरीके यहां दिए गए हैं:

selectOne(sql, args)मैच करने वाला पहला/एक JavaScript ऑब्जेक्ट दिखाता है
selectRow(table, where, args, select)आम तौर पर, इसका इस्तेमाल सामान्य मामलों में एसक्यूएल को अनदेखा करने के लिए किया जाता है
selectRows(table, where, args, callback, select)यह selectRow की तरह ही होता है, लेकिन इसका इस्तेमाल एक से ज़्यादा नतीजों के लिए किया जाता है.

फ़ीड लोड करना

Google Base से नतीजों का फ़ीड मिलने पर, हमें इसे डेटाबेस में सेव करना होता है:

content.setFeed({ id: id, JSON: json.toJSONString() });

... which calls ...

GearsBaseContent.prototype.setFeed = function(feed) {
  this.db.forceRow('BaseFeeds', feed);
}

सबसे पहले, हम JSON फ़ीड लेते हैं और toJSONString तरीके का इस्तेमाल करके, इसे स्ट्रिंग के तौर पर दिखाते हैं. इसके बाद, हम feed ऑब्जेक्ट बनाते हैं और उसे forceRow तरीके में पास करते हैं. forceRow का इस्तेमाल करके, नई एंट्री जोड़ी जा सकती है. अगर कोई एंट्री पहले से मौजूद है, तो उसे अपडेट किया जा सकता है.


खोज के नतीजे दिखाना

हमारा ऐप्लिकेशन, खोज के नतीजों को पेज के दाईं ओर मौजूद पैनल में दिखाता है. हम खोज के लिए इस्तेमाल किए गए शब्द से जुड़े फ़ीड को इस तरह से वापस लाते हैं:

GearsBaseContent.prototype.getFeed = function(url) {
  var row = this.db.selectRow('BaseFeeds', 'id = ?', [ url ]);
  return row.JSON;
}

अब हमारे पास एक लाइन के लिए JSON है. इसलिए, हम इसे वापस ऑब्जेक्ट में बदलने के लिए eval() कर सकते हैं:

eval("var json = " + jsonString + ";");

अब हम JSON से कॉन्टेंट को अपने पेज में innerHTMLing करना शुरू कर सकते हैं.


ऑफ़लाइन ऐक्सेस के लिए संसाधन स्टोर का इस्तेमाल करना

हमें कॉन्टेंट, लोकल डेटाबेस से मिल रहा है. इसलिए, यह ऐप्लिकेशन ऑफ़लाइन भी काम करना चाहिए, है न?

नहीं. समस्या यह है कि इस ऐप्लिकेशन को शुरू करने के लिए, आपको इसके वेब रिसॉर्स लोड करने होंगे. जैसे, JavaScript, सीएसएस, एचटीएमएल, और इमेज. फ़िलहाल, अगर उपयोगकर्ता ने यह तरीका अपनाया है, तो ऐप्लिकेशन अब भी काम कर सकता है: ऑनलाइन मोड में ऐप्लिकेशन शुरू करें, कुछ खोजें, ब्राउज़र को बंद न करें, और ऑफ़लाइन मोड में जाएं. इससे काम चल सकता है, क्योंकि आइटम अब भी ब्राउज़र की कैश मेमोरी में मौजूद होंगे. लेकिन, अगर ऐसा नहीं होता है, तो क्या होगा? हम चाहते हैं कि हमारे उपयोगकर्ता, रीबूट करने के बाद ऐप्लिकेशन को शुरू से ऐक्सेस कर पाएं.

इसके लिए, हम LocalServer कॉम्पोनेंट का इस्तेमाल करते हैं और अपने संसाधनों को कैप्चर करते हैं. जब किसी संसाधन (जैसे कि ऐप्लिकेशन को चलाने के लिए ज़रूरी एचटीएमएल और JavaScript) को कैप्चर किया जाता है, तो Gears इन आइटम को सेव कर लेता है. साथ ही, ब्राउज़र से मिले इन आइटम को वापस भेजने के अनुरोधों को भी कैप्चर कर लेता है. लोकल सर्वर, ट्रैफ़िक पुलिस की तरह काम करेगा और स्टोर से सेव किए गए कॉन्टेंट को वापस लाएगा.

हम ResourceStore कॉम्पोनेंट का भी इस्तेमाल करते हैं. इसके लिए, आपको सिस्टम को मैन्युअल तरीके से यह बताना होगा कि आपको कौनसी फ़ाइलें कैप्चर करनी हैं. कई स्थितियों में, आपको अपने ऐप्लिकेशन का वर्शन बनाना होता है. साथ ही, लेन-देन के तरीके से अपग्रेड करने की अनुमति देनी होती है. संसाधनों का एक सेट, किसी वर्शन को तय करता है. जब संसाधनों का नया सेट रिलीज़ किया जाता है, तो आपको यह पक्का करना होता है कि आपके उपयोगकर्ताओं को फ़ाइलों को अपग्रेड करने में कोई परेशानी न हो. अगर आपका मॉडल यही है, तो आपको ManagedResourceStore API का इस्तेमाल करना होगा.

हमारे संसाधनों को कैप्चर करने के लिए, GearsBaseContent ऑब्जेक्ट यह काम करेगा:

  1. उन फ़ाइलों का ऐरे सेट अप करें जिन्हें कैप्चर करना है
  2. LocalServer बनाना
  3. कोई ResourceStore खोलें या नया ResourceStore बनाएं
  4. स्टोर में पेजों को कैप्चर करने के लिए कॉल आउट करना
// 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'));
  });
}

यहां यह ध्यान रखना ज़रूरी है कि सिर्फ़ अपने डोमेन पर मौजूद संसाधनों को कैप्चर किया जा सकता है. हमें यह समस्या तब हुई, जब हमने SVN ट्रंक में मौजूद ओरिजनल "gears_db.js" फ़ाइल से, GearsDB JavaScript फ़ाइल को सीधे तौर पर ऐक्सेस करने की कोशिश की. इसका आसान तरीका यह है कि आपको सभी बाहरी संसाधनों को डाउनलोड करके अपने डोमेन में रखना होगा. ध्यान दें कि 302 या 301 रीडायरेक्ट काम नहीं करेंगे, क्योंकि LocalServer सिर्फ़ 200 (सफलता) या 304 (बदलाव नहीं किया गया) सर्वर कोड स्वीकार करता है.

इससे कुछ समस्याएं हो सकती हैं. अगर आपने अपनी इमेज images.yourdomain.com पर रखी हैं, तो उन्हें कैप्चर नहीं किया जा सकेगा. www1 और www2 एक-दूसरे को नहीं देख सकते. सर्वर-साइड प्रॉक्सी सेट अप की जा सकती हैं. हालांकि, इससे आपके ऐप्लिकेशन को कई डोमेन में बांटने का मकसद पूरा नहीं होगा.

ऑफ़लाइन ऐप्लिकेशन को डीबग करना

ऑफ़लाइन ऐप्लिकेशन को डीबग करना थोड़ा मुश्किल होता है. अब जांच करने के लिए, ज़्यादा स्थितियां उपलब्ध हैं:

  • मैं ऑनलाइन हूं और ऐप्लिकेशन पूरी तरह से कैश मेमोरी में चल रहा है
  • मैं ऑनलाइन हूं, लेकिन मैंने ऐप्लिकेशन को ऐक्सेस नहीं किया है. साथ ही, कैश मेमोरी में कुछ भी नहीं है
  • मैं ऑफ़लाइन हूं, लेकिन मैंने ऐप्लिकेशन को ऐक्सेस किया है
  • मैं ऑफ़लाइन हूं और मैंने कभी ऐप्लिकेशन का इस्तेमाल नहीं किया (यह अच्छी बात नहीं है!)

हमने इस पैटर्न का इस्तेमाल किया है, ताकि आपको आसानी हो:

  • जब हमें यह पक्का करना होता है कि ब्राउज़र सिर्फ़ कैश मेमोरी से कोई जानकारी नहीं ले रहा है, तब हम Firefox (या आपके चुने हुए ब्राउज़र) में कैश मेमोरी को बंद कर देते हैं
  • हम Firebug का इस्तेमाल करके डीबग करते हैं. साथ ही, अन्य ब्राउज़र पर टेस्टिंग के लिए Firebug Lite का इस्तेमाल करते हैं. हम हर जगह console.log() का इस्तेमाल करते हैं. साथ ही, हम कंसोल के लिए इसका पता लगाते हैं
  • हम हेल्पर JavaScript कोड को इनमें जोड़ते हैं:
    • हमें डेटाबेस को मिटाने और नए सिरे से शुरुआत करने की अनुमति दें
    • कैप्चर की गई फ़ाइलें हटा देता है, ताकि रिलोड करने पर, उन्हें इंटरनेट से फिर से डाउनलोड किया जा सके (यह तब काम आता है, जब आपको डेवलपमेंट पर बार-बार काम करना हो ;)

अगर आपने Gears इंस्टॉल किया है, तो डीबग विजेट सिर्फ़ पेज के बाईं ओर दिखेगा. इसमें कोड को क्लीन अप करने के लिए कॉलआउट हैं:

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();
}

नतीजा

आपको पता चल गया होगा कि Google Gears के साथ काम करना काफ़ी आसान है. हमने डेटाबेस कॉम्पोनेंट को और भी आसान बनाने के लिए, GearsDB का इस्तेमाल किया. साथ ही, हमने मैन्युअल ResourceStore का इस्तेमाल किया, जो हमारे उदाहरण के लिए ठीक काम करता है.

आप जिस इलाके में सबसे ज़्यादा समय बिताते हैं उसके हिसाब से, यह तय किया जाता है कि डेटा को ऑनलाइन कब किया जाए और उसे ऑफ़लाइन कैसे सेव किया जाए. डेटाबेस स्कीमा तय करने में समय लगाना ज़रूरी है. अगर आपको आने वाले समय में स्कीमा में बदलाव करना है, तो आपको उस बदलाव को मैनेज करना होगा. ऐसा इसलिए, क्योंकि आपके मौजूदा उपयोगकर्ताओं के पास पहले से ही डेटाबेस का एक वर्शन होगा. इसका मतलब है कि आपको डेटाबेस के किसी भी अपग्रेड के साथ स्क्रिप्ट कोड को शिप करना होगा. ज़ाहिर है, इससे इस समस्या को कम करने में मदद मिलती है. साथ ही, आपको GearShift आज़माना चाहिए. यह एक छोटी लाइब्रेरी है, जो आपको बदलावों को मैनेज करने में मदद कर सकती है.

हम अपनी फ़ाइलों को ट्रैक करने के लिए, ManagedResourceStore का भी इस्तेमाल कर सकते थे. हालांकि, ऐसा करने पर ये समस्याएं हो सकती थीं:

  • हम एक ज़िम्मेदार नागरिक की तरह काम करेंगे और अपनी फ़ाइलों को वर्शन करेंगे, ताकि आने वाले समय में अपग्रेड आसानी से किए जा सकें
  • ManagedResourceStore में एक ऐसी सुविधा होती है जिसकी मदद से, किसी यूआरएल को किसी दूसरे कॉन्टेंट का एलियास बनाया जा सकता है. आर्किटेक्चर का मान्य विकल्प यह होगा कि gears_base.js, Gears का नॉन-Gears वर्शन हो. साथ ही, उसे इस तरह से एलियास किया जाए कि Gears खुद ही gears_base_withgears.js को डाउनलोड कर ले. इसमें ऑफ़लाइन मोड में काम करने की सभी सुविधाएं होंगी.
हमें लगा कि हमारे ऐप्लिकेशन के लिए, सिर्फ़ एक इंटरफ़ेस रखना और उसे दो तरीकों से लागू करना ज़्यादा आसान होगा.

हमें उम्मीद है कि आपको Gearing up applications के बारे में जानकारी मज़ेदार और आसान लगी होगी! अगर आपके कोई सवाल हैं या आपको कोई ऐप्लिकेशन शेयर करना है, तो कृपया Google Gears फ़ोरम में शामिल हों.