Az összes ismerős lekérdezése

UPDATE: Fontos változás az ismerősök lekérdezésénél.

Az iWiW alkalmazások lekérdezhetik az alkalmazás tulajdonosának, illetve az alkalmazás nézőjének ismerőseit (erről már volt korábban szó: Mit tehet egy alkalmazás?), ám ezt illetően vannak kötöttségek, például egy lekérdezés után alapértelmezetten csak 20 ismerőst kapunk vissza, s bár ezt meg lehet növelni, de a limit 50 ismerős - vagyis lapozni kell. Az alábbiakban egy megoldást teszek közzé, mely felhasználóbarát módon teszi lehetővé az összes ismerős elérését.

A megoldás kulcsához nézzük át, hogy a newFetchPeopleRequest kérés milyen módon paraméterezhető:

  • FILTER: Szűrhetjük az ismerősök listáját, például szűkíthetjük az ismerősök listáját azokra, akiknek a jelen alkalmazás már fel van telepítve. Jelenleg csak ezt a szűrési módot támogatja az iWiW.
  • FILTER_OPTIONS: Egyes filterekhez lehet(ne) megadni további paramétereket segítségével.
  • FIRST: Ezzel határozhatjuk meg, hogy hányadik ismerőstől kérjük a listát.
  • MAX: Ezzel pedig azt, hogy maximum mennyi elemet kérünk (50-nél többet nem kérhetünk az iWiW-en).
  • PROFILE_DETAILS: Milyen profil tulajdonságokat szeretnénk lekérni - jelenleg felesleges használni, de a jövőben amikor további profil információkhoz is hozzá lehet majd férni, akkor igen hasznos lesz.
  • SORT_ORDER: Milyen sorrendben szeretnénk az ismerőseinket visszakapni. Jelenleg csak a névsort támogatja az iWiW, vagy ha nem adunk meg sorrendet, akkor valamilyen “véletlen” (belső azonosítóra épülő), de nem változó listát kapunk.

A trükkre az eddig írtakból rá lehet jönni: a FIRST és MAX paraméterek állításával fogjuk lekérdezni az összes ismerőst. Van még két trükk azonban: az egyik, hogy a kéréseket összecsomagolva csökkenthetjük a szerver felé indított kérések számát, illetve hogy először csak egy csomagot (50 ismerőst) kérünk le, s a válaszban benne levő teljes ismerősök száma tulajdonságot használjuk fel ahhoz hogy meghatározzuk, mennyi további csomagot fogunk lekérni (300 ismerősnél első kérésben 50-et, második kérésben 5 csomagban 5×50-et, avagy 250-et fogunk lekérni).

Ennek a felállásnak az is előnye, hogy az első válasz után már meg tudjuk jeleníteni a felhasználók felé az első adagot, s míg jön a többi, ő már elkezdhet tevékenykedni.

Ezekkel a funkciókkal, lehetőségekkel összeállítottam egy kész függvényt, mely ezeket a feladatokat megcsinálja mind helyettünk:

var IWIW = {};
IWIW.loadFriends = function(options) {
  // az objektumot később is fogjuk még használni, amikor a "this" más értékkel fog
  // bírni, ezért letároljuk az "obj" változóba
  var obj = this;
  // az ismerősök száma
  obj.totalSize = 0;
  // a params paraméterrel átadhatunk paramétereket a newFetchPeopleRequest hívásnak
  obj.params = options.params || {};
  // az ismerősök lekérdezését a legelején kezdjük
  obj.params[opensocial.DataRequest.PeopleRequestFields.FIRST] = 0;
  // és 50-et kérünk le (iWiW-en az egy csomagban lekérhető maximum)
  obj.params[opensocial.DataRequest.PeopleRequestFields.MAX] = 50;
  // a userId paraméter segítségével megmondhatjuk, hogy az OWNER vagy VIEWER
  // ismerőseire vagyunk-e kíváncsiak
  var userId = options.userId;
  // az onFirstFriends egy függvény, mely akkor hívódik meg, amikor az első ismerős
  // csomag megérkezik
  var onFirstFriends = options.onFirstFriends || function(){};
  // az onAllFriends egy függvény, mely akkor hívódik meg, amikor az összes ismerős
  // csomag megérkezett
  var onAllFriends = options.onAllFriends || function(){};
  // egy adatlekérés objektumot hozunk létre
  var request = opensocial.newDataRequest();
  // egy csoportot definiálunk: az alkalmazás nézőjének vagy tulajdonosának (userId) az ismerőseit
  obj.usergroup = opensocial.newIdSpec({"userId": userId, "groupId": "FRIENDS"});
  // a kéréshez hozzáadjuk az előbb definiált csoport lekérdezését, a választ
  // "friends0" néven fogjuk visszakapni
  request.add(request.newFetchPeopleRequest(obj.usergroup, obj.params), "friends0");
  // a függvény, mely az első adatlekérés után fut le
  var firstReady = function(response) {
    // itt a this értéke különbözik az eredeti objektumunktól,
    // ezért is használjuk az obj változót.
    // az obj.friends egy tömb lesz, melybe a válasz csomagokat pakoljuk
    obj.friends = [response.get("friends0").getData()];
    // a válaszban benne van az az információ, hogy összesen mennyi ismerős van, letároljuk
    obj.totalSize = obj.friends[0].getTotalSize();
    // a size értéke a jelen csomagban érkezett ismerősök száma (jellemzően 50, hacsak nincs
    // 50-nél kevesebb ismerőse a felhasználónak)
    var size = obj.friends[0].size();
    // a pozíció, ahol az ismerősök listájával járunk (0, 50, 100, stb. lesz)
    var pos = 0;
    // ha nem jött meg az összes ismerős, akkor...
    if (size < obj.totalSize) {
      // meghívjuk az első ismerősök megérkezésekor lefutó függvényt
      onFirstFriends(obj);
      // egy adatlekérés objektumot hozunk létre
      var request = opensocial.newDataRequest();
      // amíg nem érjük el az ismerősök számát...
      while (pos + size < obj.totalSize) {
        // következő csomag ott kezdődik, ahol az előző abbamaradt
        pos += size;
        // beállítjuk, hogy honnantól kezdje letölteni az ismerősöket, mi legyen az első elem
        obj.params[opensocial.DataRequest.PeopleRequestFields.FIRST] = pos;
        // a kéréshez hozzáadjuk a korábban már definiált csoport lekérdezését, a választ
        // "friendsXXX" néven fogjuk visszakapni, ahol az XXX a pozíció
        request.add(request.newFetchPeopleRequest(obj.usergroup, obj.params), "friends"+pos);
      }
      // elküldjük a több csomagot is tartalmazó kérést (második kérés)
      request.send(allReady);
    } else {
      // ha az első kérés során megjött az összes ismerős, akkor csak az onAllFriends kerül
      // meghívásra, mert már most tartalmazza az összes ismerőst.
      onAllFriends(obj);
    }
  }
  // a függvény, melyet a második lekérdezés válaszának megérkezésekor hívunk meg
  var allReady = function(response) {
    // csomag változó
    var package;
    // az első csomag végéről indulunk
    var pos = obj.friends[0].size();
    // ha nem értünk a végére, akkor...
    while (pos < obj.totalSize) {
      // a csomagot kivesszük a válaszból
      var package = response.get("friends"+pos).getData();
      // és betesszük az obj.friends tömbbe
      obj.friends.push(package);
      // növelkjük a pozíciót
      pos += package.size();
    }
    // meghívjuk az onAllFriends függvényt az összes ismerőssel
    onAllFriends(obj);
  }
  // elküldjük a lekérdezést, a függvény paramétere egy másik függvény,
  // ami akkor kerül meghívásra, amikor a szervertől megérkezik a válasz
  request.send(firstReady);
  // visszatérünk az IWIW.loadFriends objektumunkkal, ez egyelőre elég üres
  // de már beindítottuk az első lekérdezést, melyre hamarosan megjön a válasz
  return this;
};

A függvényt igyekeztem elég jól dokumentálni sok-sok megjegyzéssel, a kódban benne van tehát a magyarázat - emiatt nem írnám le még egyszer hogy pontosan hogyan működik. Összefoglalva: egy vagy két kérést indítunk a szerver felé, második kérést csak akkor, ha az első 50 elembe nem fért bele az összes ismerős. A második kérésben annyi csomagban kérjük le az ismerősöket, hogy immár a teljes ismerősi kör beleférjen. Paraméterként két függvényt adhatunk át, az első az első kérés után fut le (ha nem jött meg az összes ismerős), míg a második akkor, ha megjött az összes. A megkapott objektum friends tömbjében lesznek benne a szervertől visszakapott válaszok.

A függvény használatára egy példa, így valószínűleg még érthetőbb lesz:

// új kérés
new IWIW.loadFriends({
  // a tulajdonos ismerőseit fogjuk lekérdezni
  userId: "OWNER",
  // ha megjött az első adag ismerős
  onFirstFriends: function(response) {
    // az objektum friends tulajdonsága a fentebb emlegetett tömb
    var friends = response.friends;
    // a friends tömbnek még csak egy eleme van
    friends[0].each(function(person){
      // person.getDisplayName() használható, például
    })
  },
  // ha megjött az összes ismerős
  onAllFriends: function(response) {
    // az objektum friends tulajdonsága a fentebb emlegetett tömb
    var friends = response.friends;
    // végigmegyünk a tömb elemein, a csomagokon
    for(var i=0; i<friends.length; i++) {
      // minden csomagból kiolvassuk a benne levő személyeket
      friends[i].each(function(person){
        // person.getDisplayName() használható, például
      })
    }
  }
});

2 megjegyzés - “Az összes ismerős lekérdezése”


  1. 1 Akos

    Nem egészen értem, hogy minek leszűkiteni hogy mennyi ismerőst tudunk lekérni, ha azután kapunk egy eszközt ennek a megkerülésére?
    Amúgy kösz az eszközt, (felhasználhatjuk, ugye?) megsporoltál egy adag melót!

  2. 2 devblogger

    Akos: Mert ez nem az az eszköz amit mindig használni kell, de elképzelhetőek olyan funkciók, amikhez szükséges lehet az összes ismerős lekérdezése. Azért mert írtunk róla, továbbra sem támogatjuk azt, ha valaki indokolatlanul kérdezi le az összes ismerőst egy alkalmazásban. A jóváhagyási folyamatnak ezért is része az alkalmazás technikai ellenőrzése.

Hagyj egy megjegyzést