10
votes

Comment détecter la fin d'une chaîne de méthode en JavaScript?

Premièrement et surtout, j'essaie de détecter l'appel final d'une chaîne de méthode. Je tiens également à concevoir un moyen de détecter le nombre de méthodes "dans" ou "Down" une chaîne d'objets, je suis dans mes appels de méthode dans une chaîne de méthode.

Par exemple, dans le plugin que j'écris: xxx

dire que la méthode exécute actuellement dans .bar () Je voudrais savoir que j'ai 2 méthodes dans la chaîne.

La raison dont j'ai besoin Pour résumer ces informations, de quelque manière que ce soit lorsque j'atteindra la dernière méthode de la chaîne, je peux retourner un résultat à la place de l'objet du plug-in en cas de rupture de la chaîne à ce stade pour obtenir un accès à nos données dans la variable "résultat" .


8 commentaires

Si j'ai bien compris le problème, je préférerais faire une méthode .Result () appelée la dernière et qui renvoie la valeur souhaitée.


Donnez à votre dernière fonction un paramètre le dire s'il s'agit du dernier dans la chaîne.


Juhana - J'avais pensé à cela, mais j'aimerais trouver un moyen pour l'utilisateur de renvoyer les données à une variable sans avoir à apporter une méthode supplémentaire.


Ilia g - Il n'ya aucun moyen de déterminer dans quel ordre les méthodes seront appelées, il n'y a malheureusement pas de dernière méthode dans la chaîne.


Si j'avais utilisé ce plugin, je ne voudrais jamais que ce genre de fonctionnalité, mais votre appel.


Juhana - Considérant que vous ne savez pas ce que le plugin est, c'est une déclaration importante à faire. Le plugin vous permet de travailler sur les données de PHP renvoyées directement dans JavaScript. En fait, c'est la principale manière que vous voudriez utiliser ce plugin spécifique.


Pour obtenir le nombre ou dans, vous pouvez ajouter un compteur qui incrémenté chaque fois qu'une méthode est appelée, de sorte que si elle se termine dans la barre (), elle a incrémenté deux fois et vous êtes donc 2 en bas de la chaîne.


Dwolf - Tu as raison. Et comme cela arrive, j'ai juste fait ceci pour déterminer quelle position de méthode je suis à. Donc, cette partie de la question est répondue. Maintenant, j'ai juste besoin de créer un moyen de trouver la dernière méthode de la chaîne. Les pensées?


5 Réponses :


1
votes

Il n'y a pas de moyen (légal ou facile ou gentil) de savoir à l'intérieur une méthode qui se produit avec le résultat dehors , après son retour avec elle. Vous devez utiliser une méthode de «marque de chaîne».

Réfléchissez à nouveau, recherchez-vous la dernière méthode appliquée sur un objet, ou voulez-vous détecter quelque chose de plus d'explicite? Peut-être que vous perdez une possibilité d'appliquer des méthodes sur une décision (avec de faux noms de méthode idius): xxx


10 commentaires

Je ne m'attardais pas dans le monde de "légal ou facile ou gentil". ;) Je ne cherche pas la dernière méthode appliquée sur un objet, je suis simple que je veux détecter la dernière méthode pour renvoyer le résultat calculé. Peut-être en consultant mon plugin, vous pourriez mieux comprendre mon intention: github.com/xaxis/jqueryphp


Ouch, c'est une idée courageuse! Donc, si je comprends bien, votre objectif est de "garder" des appels de chaîne sur le côté serveur au lieu d'effectuer une demande HTTP séparée pour chacune?


Si oui, vos méthodes .dothis () .DOTHAT () shuld () Ajouter un élément de commande ("this" et "tandis") à la queue de commande de l'objet , et le Final LastMethod ... () Devrait être celui qui publie cette file d'attente sur le côté du serveur, puis il appartient au serveur d'effectuer toutes les méthodes en file d'attente et de renvoyer la finale - résultat final. (Si je comprends votre vrai problème.)


N'aimez-vous pas la syntaxe: obj.phpcall ("phpfunct", parm1, parm2) .phpcall ("autrephpfuncct woparm"). Effectuer (); ?


Wow @xaxis, c'est courageux, en effet. Et pourrais-je aller aussi loin que c'est aussi mauvais cul! C'est donc ma compréhension que vous avez déjà besoin d'une fonction de rappel - mais cela pourrait simplement être défini à portée de main. Donc l'ensemble, "Garder une variable dans MyPlugin qui est écrasé par toutes les fonctions de votre chaîne", la chose devrait fonctionner super (voir ma réponse mise à jour) - sans avoir besoin d'utiliser Settimeout depuis que vous serez faire un appel asynchrone, de toute façon.


@Xaxis: En regardant d'autres exemples (où vous utilisez .data ) Je peux voir que ma réponse n'est pas assez adéquate. Je remarque que vous utilisez parseint sur strylen . Est-ce que .Data renvoie toujours un type de chaîne?


@ ern0 - Oui. Je suis en train de développer la fonctionnalité pour conserver toutes mes demandes dans un bloc, puis envoyez-les au serveur. En effet, avec une "file d'attente de commande", je serai facilement en mesure de détecter la fin de la pile et mon problème de détection de la méthode de fin dans une chaîne serait résolu. À ce stade, le plugin ne fonctionne pas encore de cette manière.


@Grinn - Une fonction de rappel est uniquement requise si l'on souhaite retourner des résultats dans le DOM, comme comme le HTML intérieur d'un DIV ou de quelque chose de similaire. De plus, à ce stade, la majeure partie de la logique du plugin ne fonctionne que avec des appels synchrones sur le serveur.


@Grinn - Oui Un type de chaîne est toujours renvoyé même si cette chaîne se trouve être une chaîne JSON dans des cas lorsqu'un "tableau" est renvoyé par PHP. Il a été à l'arrière de mon esprit de développer une sorte de logique de type de type de type afin que les utilisateurs n'ayant pas à se soucier de analyser quoi que ce soit.


@Xaxis: J'ai ajouté une deuxième réponse qui devrait fonctionner pour vous pour vous, puis. À l'avenir, vous pouvez utiliser la valeurOf pour d'autres types de données.



1
votes

Il n'est pas possible de déterminer si un appel est la dernière instance d'une chaîne lors de la détermination de la valeur de retour , et voici pourquoi: xxx

< code> foo renvoie myplugin sur lequel bar est appelé quel retour myplugin sur lequel _foo est appelé qui retourne myplugin sur lequel _bar est appelé.

si efficacement, lorsque _foo renvoie sa valeur ( MyPlugin ), il est avant que cette valeur soit utilisée. Sauf si _foo est psychique, il ne peut pas savoir ce qui va se passer ensuite.

Comme indiqué dans vos commentaires, votre meilleur pari est d'avoir une méthode "finale", comme < Code> Résultats () .

Une autre suggestion serait de transmettre un gestionnaire dans myplugin qui est appelé à définir la valeur à l'aide de Settimeout (.. ., 0) . Avoir une valeur dans myplugin que foo, bar, _foo et _bar tous ensemble. Appelons-le retourvalue . Modifiez MyPlugin pour accepter une méthode car il est uniquement paramètre. Appelons ce gestionnaire . Le premier argument de cette méthode contiendra la valeur. À l'intérieur de MyPlugin, avant votre retour , faites: xxx

puisque le paramètre de fonction de SettimeOut ne sera appelé que lorsque l'exécution soit terminée, elle contiendra le dernier Valeur définie pour retourvalue - efficacement la valeur définie par le dernier appel de la chaîne. J'envisagerais cette option la plus proche de ce que vous essayez d'atteindre, car le développeur n'a pas à s'inquiéter de laquelle de ses méthodes sont appelées en dernier.


6 commentaires

Oui, je suis parfaitement conscient que chaque retour est le plugin lui-même (rendant ainsi le modèle de chaînage possible). L'astuce serait une condition qui détecte l'appel de la dernière méthode et dans cette situation renvoie les données de résultat vs. Le plugin lui-même. J'apprécie votre contribution mais je refuse de croire que ce n'est pas possible à ce stade.


Eh bien, j'apprécie votre zèle! Donc, vous avez absolument besoin de l'avoir au retour , non? Sinon, il y a quelques options supplémentaires.


Comme, seriez-vous prêt à faire var résultat = $ ("# somediv"). Myplugin.foo (). Bar () ._ foo () ._ bar () (); ou ou ou ou $ ("# somediv"). Myplugin.foo (). bar () ._ foo () ._ bar (résultat); ou $ ("# somediv"). MyPlugin (résultat) .foo ( ) .Bar () ._ foo () ._ bar (); ?


Ce que je fais actuellement est juste: $ ("# somediv"). Myplugin.foo (). Bar () ._ foo (). Somemethod (). Données une propriété pour contenir les données de retour qui fonctionne très bien. C'est juste que je préférerais vraiment ne pas avoir besoin de le faire.


Eh bien, j'ai inclus une explication de comment faire $ ("# somediv"). MyPlugin (résultat) .foo (). Bar () ._ foo () ._ bar (); car il est plus étroitement ressemble à ce que vous essayez d'essayer. Le développeur n'aura toujours pas besoin de garder une trace de quelle méthode s'appelle la dernière dans la chaîne, mais je sais que ce n'est pas exactement ce que vous vouliez.


Oui, j'ai envisagé de passer un drapeau comme paramètre sur le plug-in si vous souhaitez transmettre l'utilisateur à transmettre le nom de la dernière méthode de la chaîne ou peut-être le nombre de méthodes de la chaîne ou de toute façon qui me permettrait de définir une condition de retourner Les données après la dernière méthode appelent mais jusqu'à présent, je pense que le moyen le plus élégant est de les avoir simplement d'ajouter la propriété .Data à la fin de la chaîne pour renvoyer le résultat à une variable. ... Néanmoins, comme vous le savez, je voudrais également vous débarrasser de la nécessité de cette exigence. : - \



4
votes

Voici un exemple retiré de Votre projet :

var stringMagic = function() {
    var chain = "",
        self = this;
    self.toString = function () { return chain; }; // Where the real magic happens.
    self.add = function(str) {
        chain += str + " ";
        return self;
    };
};


var magi = new stringMagic();
alert(magi.add("hello").add("world")); // Alerts, "hello world"
magi.add("and").add("thanks").add("for").add("all").add("the").add("fish");
alert(magi); // Alerts, "hello world and thanks for all the fish"


4 commentaires

J'apprécie vraiment votre intérêt et vos efforts. Tu m'as donné une bonne nourriture pour la pensée. Je suis allé de l'avant et j'ai mis en œuvre une analyse de type de données. J'ai également ajouté la fonctionnalité pour utiliser des blocs JSON spécialement formés remplis de «code» PHP. Ces blocs sont exécutés tous à la fois sur le serveur et le résultat final est renvoyé.


Mon plaisir. C'était un défi intéressant, alors je me suis trompé. Par curiosité, pourquoi avez-vous collé avec .Data et .result () / .end () au lieu de mettre en œuvre quelque chose comme Tostring / ValueOf ? J'avais envisagé d'utiliser la valeur / / sur un projet moi-même mais je ne voudrais pas si vous avez trouvé un problème avec cela.


Il n'y a pas de différence avec les solutions précédemment proposées de mettre fin à la chaîne avec .result (). Cette solution ne fonctionne que parce que les chaînes sont transmises comme paramètres et alerte s'appliquent .Tostring () à n'importe quel objet non chaîne. Dans tout autre contexte, avec magic = maged.add ("Bonjour"). Ajouter ("World"), Magic est un objet et une sortie () doit être appelé à renvoyer le texte actuel.


@Widget. Vous êtes sur la bonne voie, mais il y a une différence. La différence est que la fonctionnalité de .result () est implémentée dans .tostring () à la place. En regardant ce que l'OP essaie réellement d'accomplir dans son cas (lisez la première partie de ma réponse ci-dessus), cela est pertinent pour aider à résoudre son problème réel. Lorsqu'un objet est traité comme une chaîne, JavaScript utilise automatiquement la méthode .tostring . Par exemple, MAGI.Ajoud ("Bonjour"). Ajouter ("Monde") + "S" === "Hello Worlds" . Si cela ne vous aide pas dans votre scénario, alors je vous suggère de rechercher une solution différente.



2
votes

Par souci de complétude. Encore une autre alternative consiste à adopter un objet qui sera mis à jour au fur et à mesure de la progression de la chaîne. Cela vous permettrait d'accéder à la valeur de résultat chaque fois que vous vous convient (au lieu de devoir l'ajouter à la fin de la chaîne).

au lieu d'une syntaxe comme celle-ci: p> xxx pré>

vous auriez alors: p> xxx pré>

la logique est beaucoup la même que la solution proposée par d'autres. Lequel utiliser dépend probablement de vos cas d'utilisation. Un problème possible d'avoir à mettre fin à la chaîne avec .result est que rien ne vous empêche de l'utiliser de cette façon: p>

#!/usr/bin/env node

var ChainUp = {};
(function(Class) {

  // Pure functions have no access to state and no side effects
  var Pure = {};
  Pure.isFunction = function(fn) {
     return fn && {}.toString.call(fn) === '[object Function]';
  };

  Class.instance = function() {
    var instance = {};
    var result;
    var updateRef;

    function callBack(fn) {
      // returning a clone, not a reference.
      if(updateRef) { updateRef.r = (result || []).slice(0); } 
      if(Pure.isFunction(fn)) { fn(result); }
    }

    instance.update = function(obj) {
      updateRef = obj;
      return instance;
    };

    instance.one = function(cb) {
        result = (result || []); result.push("one");
        callBack(cb);
        return instance;
      };
      instance.two = function(cb) {
        result = (result || []); result.push("two");
        callBack(cb);
        return instance;
      };
      instance.three = function(cb) {
        result = (result || []); result.push("three");
        callBack(cb);
        return instance;
      };
      instance.result = function() {
        return result;
      };
    return instance;
  };

}(ChainUp));


var result1 = {};
var chain = ChainUp.instance().update(result1);
var one = chain.one(console.log); // [ 'one' ]
console.log(one.result());        // [ 'one' ]
console.log(result1.r);           // [ 'one' ]

var oneTwo = chain.two(); 
console.log(oneTwo.result());  // [ 'one', 'two' ]
console.log(result1.r);        // [ 'one', 'two' ]

var result2 = {};
var oneTwoThree = chain.update(result2).three();
console.log(oneTwoThree.result()); // [ 'one', 'two', 'three' ]
console.log(result2.r);            // [ 'one', 'two', 'three' ]

console.log(result1.r);             // [ 'one', 'two' ]


0 commentaires

0
votes

Il n'y a pas de manière native, cependant, vous pouvez ajouter un paramètre à la méthode destinée à être chaînée que vous le souhaitez. Et déterminez si l'appel en cours est le dernier en la définissant sur true , comme dans: xxx


0 commentaires