web-dev-qa-db-fra.com

Meteor.methods renvoie undefined

J'utilise Meteor 0.6.4.

Meteor.methods({
  random: function(top){
    var random = Math.floor((Math.random()*(top+1)));
    return random;
  }
});

Il retourne indéfini chaque fois que j'exécute

Meteor.call('random', 10);

Avez-vous des idées sur la façon de surmonter cela?

31
jaggy

C'est un comportement parfaitement normal: les appels de méthode serveur dans Meteor sont documentés pour être asynchrones:

Sur le client, si vous ne passez pas de rappel et que vous n'êtes pas dans un stub, l'appel renverra non défini et vous n'aurez aucun moyen d'obtenir la valeur de retour de la méthode.

Cela signifie que lorsque vous demandez un Meteor.call méthode à exécuter à distance sur le serveur, l'appel de méthode locale n'est pas bloquant et renvoie immédiatement undefined. Lorsque la méthode a été appelée sur le serveur, elle enverra le résultat de manière asynchrone au client, vous devez donc le récupérer à l'aide du modèle de rappel:

Meteor.call("myMethod", arguments..., function(error, result){
  if(error){
    console.log(error.reason);
    return;
  }
  // do something with result
});

La fonction de rappel anonyme sera appelée sur le client dès que le résultat de la méthode serveur sera renvoyé au client.

Il y a une autre fonctionnalité subtile dans Meteor qui invalide ce que je viens de dire: compensation de latence et stubs de méthodes. Dans le cas où l'appel de méthode serveur peut être SIMULÉ correctement dans le client et ainsi exécuté immédiatement sans aller-retour vers le serveur, vous pouvez définir ce qu'on appelle un stub (ou simulation) de méthode.

Un cas d'utilisation courant de ce comportement consiste à insérer immédiatement dans la base de données locale (sous-ensemble de réplication côté client) du contenu utilisateur qui vient d'être publié (un commentaire dans un article de blog par exemple): toutes les données et la logique nécessaires sont disponibles et il est logique de simuler insertion côté serveur. Ce qui se passe ensuite, c'est que l'utilisateur voit la page Web mise à jour dès qu'il a soumis son contenu, même si le serveur n'a pas encore reconnu ces modifications. (c'est un exemple de la façon dont la compensation de latence est implémentée dans Meteor).

Bien sûr, le serveur a le dernier mot sur ce qui est finalement inséré dans la base de données, cela signifie que lorsque la méthode double côté serveur est exécutée, ses actions auront la priorité et remplaceront ce qui a été inséré dans la base de données locale.

Pour définir un tel stub de méthode, il vous suffit de définir le même nom de méthode serveur sur le code client. Si la déclaration de méthode est définie dans du code partagé (livré à la fois au client et au serveur), vous pouvez tester si l'appel de méthode est en fait une simulation en vérifiant la propriété isSimulation:

Meteor.methods({
    myMethod: function(arguments...){
        if(this.isSimulation){
            // called from the client
        }
    }
});

MISE À JOUR 26/11/2014: @ steph643 a commenté la façon dont la dernière partie de ma réponse précédente était en fait incorrecte, voici une correction.

Notez que sur la méthode du serveur, les appels peuvent toujours être appelés à l'aide de la syntaxe synchrone car l'environnement du serveur fournit un mécanisme de blocage adéquat (fibres).

Sur le client cependant, si vous retournez quelque chose à partir d'un stub de méthode, il ne peut être exécuté de manière synchrone que si vous êtes à l'intérieur d'un autre stub et vous pouvez récupérer le résultat de manière synchrone, c'est-à-dire

Meteor.methods({
  intermediateMethod: function(){
    return " WORLD";
  },
  method: function(){
    var result = "HELLO";
    result += intermediateResult;
    var intermediateResult = Meteor.call("intermediateMethod");
    return result;
  }
});

Ce comportement est un peu bizarre si l'on considère que les opérations de collecte Mongo (insertion/mise à jour/suppression) sont implémentées comme des méthodes Meteor et leurs versions client implémentent des stubs valides (modification du sous-ensemble de base de données locale répliqué minimongo) qui peuvent être exécutés de manière synchrone.

61
saimeunt