sql >> Database teknologi >  >> NoSQL >> MongoDB

Hvad sker der med Meteor og Fibres/bindEnvironment()?

Du bruger bindEnvironment lidt forkert. Fordi hvor den bruges allerede er i en fiber, og det tilbagekald, der kommer fra Knox-klienten, er ikke længere i en fiber.

Der er to use cases af bindEnvironment (som jeg kan komme i tanke om, der kunne være flere!):

  • Du har en global variabel, der skal ændres, men du ønsker ikke, at den skal påvirke andre brugers sessioner

  • Du administrerer et tilbagekald ved hjælp af et tredjeparts api/npm-modul (hvilket ser ud til at være tilfældet)

Meteor.bindEnvironment opretter en ny Fiber og kopierer den nuværende Fibers variabler og miljø til den nye Fiber. Det punkt, du har brug for dette, er, når du bruger dit nom-moduls metode til tilbagekald.

Heldigvis er der et alternativ, der tager sig af tilbagekaldet, der venter på dig og binder tilbagekaldet i en fiber kaldet Meteor.wrapAsync .

Så du kunne gøre dette:

Din opstartsfunktion har allerede en fiber og ingen tilbagekald, så du behøver ikke bindEnvironment her.

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

Og din insert records-funktion (ved hjælp af wrapAsync), så du ikke behøver et tilbagekald

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

Et par ting at huske på. Fibre er ikke som tråde. Der er kun en enkelt tråd i NodeJS.

Fibre er mere som begivenheder, der kan køre på samme tid, men uden at blokere hinanden, hvis der er et ventende scenarie (f.eks. download af en fil fra internettet).

Så du kan have synkron kode og ikke blokere den anden brugers begivenheder. De skiftes til at løbe, men kører stadig i en enkelt tråd. Så det er sådan, Meteor har synkron kode på serversiden, som kan vente på ting, men andre brugere vil ikke blive blokeret af dette og kan gøre ting, fordi deres kode kører i en anden fiber.

Chris Mather har et par gode artikler om dette på http://eventedmind.com

Hvad gør Meteor.wrapAsync?

Meteor.wrapAsync tager den metode, du giver den, som den første parameter og kører den i den aktuelle fiber.

Det vedhæfter også et tilbagekald til det (det antager, at metoden tager en sidste parameter, der har et tilbagekald, hvor den første parameter er en fejl, og den anden er resultatet såsom function(err,result) .

Tilbagekaldet er bundet til Meteor.bindEnvironment og blokerer den aktuelle Fiber, indtil tilbagekaldet udløses. Så snart tilbagekaldet udløses, returnerer det result eller kaster err .

Så det er meget praktisk til at konvertere asynkron kode til synkron kode, da du kan bruge resultatet af metoden på næste linje i stedet for at bruge et tilbagekald og indlejre dybere funktioner. Det tager sig også af bindemiljøet for dig, så du ikke behøver at bekymre dig om at miste din fibers omfang.

Opdater Meteor._wrapAsync er nu Meteor.wrapAsync og dokumenteret.




  1. MongoDb PHP driver installationsproblem på wamp

  2. MongoDB $erstatAlle

  3. MongoDB $prøve

  4. Uafhængig af store og små bogstaver sortering i MongoDB