sql >> Databasteknik >  >> NoSQL >> MongoDB

Vad händer med Meteor och Fibres/bindEnvironment()?

Du använder bindEnvironment något felaktigt. För där den används redan finns i en fiber och återuppringningen som kommer från Knox-klienten finns inte längre i en fiber.

Det finns två användningsfall av bindEnvironment (som jag kan komma på, det kan finnas fler!):

  • Du har en global variabel som måste ändras men du vill inte att den ska påverka andra användares sessioner

  • Du hanterar en återuppringning med hjälp av en tredje parts api/npm-modul (vilket ser ut att vara fallet)

Meteor.bindEnvironment skapar en ny Fiber och kopierar den aktuella Fiberns variabler och miljö till den nya Fibern. Punkten du behöver detta är när du använder din nom-moduls metod för återuppringning.

Lyckligtvis finns det ett alternativ som tar hand om återuppringningen som väntar på dig och binder återuppringningen i en fiber som heter Meteor.wrapAsync .

Så du kan göra så här:

Din startfunktion har redan en fiber och ingen återuppringning så du behöver inte bindEnvironment här.

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

Och din infogningsfunktion (med wrapAsync) så att du inte behöver en återuppringning

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

Ett par saker att tänka på. Fibrer är inte som trådar. Det finns bara en enda tråd i NodeJS.

Fibrer är mer som händelser som kan köras samtidigt men utan att blockera varandra om det finns ett scenario av väntande typ (t.ex. att ladda ner en fil från internet).

Så du kan ha synkron kod och inte blockera den andra användarens händelser. De turas om att springa men går ändå i en enda tråd. Så det här är hur Meteor har synkron kod på serversidan, som kan vänta på saker, men andra användare kommer inte att blockeras av detta och kan göra saker eftersom deras kod körs i en annan fiber.

Chris Mather har ett par bra artiklar om detta på http://eventedmind.com

Vad gör Meteor.wrapAsync?

Meteor.wrapAsync tar in metoden du ger den som första parameter och kör den i den aktuella fibern.

Den bifogar också en callback till den (den antar att metoden tar en sista param som har en callback där den första paramen är ett fel och den andra resultatet som function(err,result) .

Återuppringningen är bunden med Meteor.bindEnvironment och blockerar den aktuella fibern tills återuppringningen aktiveras. Så snart återuppringningen aktiveras returnerar den result eller kastar err .

Så det är väldigt praktiskt för att konvertera asynkron kod till synkron kod eftersom du kan använda resultatet av metoden på nästa rad istället för att använda en återuppringning och kapsla djupare funktioner. Den tar också hand om bindningsmiljön åt dig så att du inte behöver oroa dig för att förlora fiberns omfattning.

Uppdatera Meteor._wrapAsync är nu Meteor.wrapAsync och dokumenterat.




  1. Stackexchange.redis saknar WAIT-stödet

  2. Hur man anropar db.Collection.stats() från Mongo Java-drivrutin

  3. Hur man använder kryptering för att skydda dina MongoDB-data

  4. Exempel på användning av socket.io-redis