sql >> Databáze >  >> NoSQL >> MongoDB

Co se děje s Meteor and Fibers/bindEnvironment()?

Používáte bindEnvironment trochu nesprávně. Protože tam, kde se používá, je již vlákno a zpětné volání, které přichází z klienta Knox, již není ve vláknu.

Existují dva případy použití bindEnvironment (které mě napadají, mohlo by jich být více!):

  • Máte globální proměnnou, kterou je třeba změnit, ale nechcete, aby ovlivňovala relace ostatních uživatelů

  • Spravujete zpětné volání pomocí modulu API/npm třetí strany (což vypadá, že tomu tak je)

Meteor.bindEnvironment vytvoří nové Fiber a zkopíruje aktuální Fiber proměnné a prostředí do nového Fiber. Bod, který potřebujete, je, když používáte zpětné volání metody vašeho modulu nom.

Naštěstí existuje alternativa, která se postará o zpětné volání, které na vás čeká, a spojí zpětné volání do vlákna s názvem Meteor.wrapAsync .

Takže můžete udělat toto:

Vaše spouštěcí funkce již má vlákno a žádné zpětné volání, takže zde nepotřebujete bindEnvironment.

Meteor.startup(function () {
   if (Projects.find().count() === 0) {
     insertRecords();
   }
});

A vaše funkce vkládání záznamů (pomocí wrapAsync), takže nepotřebujete zpětné volání

function insertRecords() {
  console.log("inserting...");
  var client = Knox.createClient({
    key: apikey,
    secret: secret,
    bucket: 'profile-testing'
  });
      
  client.listSync = Meteor.wrapAsync(client.list.bind(client));

  console.log("created client");
      
  try {
      var data = client.listSync({ prefix: 'projects' });
  }
  catch(e) {
      console.log(e);
  }    

  if(!data) return;


  for (var i = 1; i < data.Contents.length; i++)  {
    console.log(data.Contents[i].Key);
    if (data.Contents[i].Key.split('/').pop() == "") {
      Projects.insert({ name: data.Contents[i].Key, contents: [] });
    } else if (data.Contents[i].Key.split('.').pop() == "jpg") {
      Projects.update( { name: data.Contents[i].Key.substr(0,
                         data.Contents[i].Key.lastIndexOf('.')) },
                       { $push: {contents: data.Contents[i].Key}} );
    } else {
      console.log(data.Contents[i].Key.split('.').pop());
    }
  }      
});

Je třeba mít na paměti několik věcí. Vlákna nejsou jako nitě. V NodeJS je pouze jedno vlákno.

Vlákna jsou spíše události, které mohou běžet současně, ale bez vzájemného blokování, pokud existuje scénář typu čekání (např. stahování souboru z internetu).

Takže můžete mít synchronní kód a neblokovat události druhého uživatele. Střídají se v běhu, ale stále běží v jediném vláknu. Takže takhle má Meteor synchronní kód na straně serveru, který může čekat na věci, ale ostatní uživatelé tím nebudou blokováni a mohou dělat věci, protože jejich kód běží v jiném vláknu.

Chris Mather má na toto téma několik dobrých článků na http://eventedmind.com

Co dělá Meteor.wrapAsync?

Meteor.wrapAsync vezme metodu, kterou zadáte jako první parametr, a spustí ji v aktuálním vláknu.

Také k němu připojí zpětné volání (předpokládá, že metoda vezme poslední parametr, který má zpětné volání, kde první parametr je chyba a druhý výsledek, jako je function(err,result) .

Zpětné volání je spojeno s Meteor.bindEnvironment a zablokuje aktuální vlákno, dokud se nespustí zpětné volání. Jakmile se spustí zpětné volání, vrátí result nebo vyvolá err .

Je to velmi užitečné pro převod asynchronního kódu na synchronní kód, protože můžete použít výsledek metody na dalším řádku namísto použití zpětného volání a vnoření hlubších funkcí. Také se za vás postará o bindEnvironment, takže se nemusíte bát, že ztratíte rozsah vašeho vlákna.

Aktualizovat Meteor._wrapAsync je nyní Meteor.wrapAsync a zdokumentováno.




  1. vysvětlit() v Mongodb:rozdíly mezi nscanned a nscannedObjects

  2. Proč je výkon Redis SET lepší než GET?

  3. Jak implementovat proud futures pro blokovací hovor pomocí futures.rs a Redis PubSub?

  4. MongoDB Schema Design – Mnoho malých dokumentů nebo méně velkých dokumentů?