Séquence d'exécution de la méthode d'action

Je suis coincé dans une situation vraiment bizarre ici. C'est compliqué à expliquer, mais je ferai de mon mieux.

J'ai une interface utilisateur avec 4 boutons <a> navigation en haut – au centre, il y a toujours un formulaire – et en bas, j'ai les boutons Précédent et Suivant.

Entrez la description de l'image ici

Les formulaires sont construits dans MVC à l'aide de Ajax.BeginForm

Pour chaque lien Nav <a> élément en haut, j'ai une fonction JavaScript

 var LoadTabs = function (e, arg) { // This is to validate a form if one of the top links is clicked and form has incomplete fields... if (arg !== "prev" && arg !== "next") { if (!window.ValidateForm(false)) return false; } var url = $(this).attr('data'); // this contains link to a GET action method if (typeof url != "undefined") { $.ajax(url, { context: { param: arg } }).done(function (data) { $('#partialViewContainer').html(data); }); } } 

Cette fonction ci-dessus se lie à chaque lien supérieur sur la charge de page.

 $('.navLinks').on('click', LoadTabs); 

Mes boutons Suivant et Précédent déclenchent essentiellement l'événement de clic, c'est-à- LoadTabs fonction LoadTabs .

 $('button').on('click', function () { if (this.id === "btnMoveToNextTab") { if (!window.ValidateForm(true)) return false; $.ajax({ url: url, context: { param: 'next' }, method: "GET", data: data, success: function(response) { if (typeof response == 'object') { if (response.moveAhead) { MoveNext(); } } else { $('#mainView').html(response); } ScrollUp(0); } }); } if (this.id === "btnMoveToPreviousTab") { MoveBack(); } return false; }); MoveNext() Implementation is as below: function MoveNext() { var listItem = $('#progressbarInd > .active').next('li'); listItem.find('.navLink').trigger('click', ['next']); ScrollUp(0); } 

Le problème est, pour certaines raisons, lorsque Nav Link 3 est actif et je frappe le bouton NEXT – Au lieu de publier le formulaire d'abord via form.submit () – le nav 4 est déclenché – donc GET for nav 4 runs before form POST of Nav 3.

Ma méthode ValidateForm consiste simplement à vérifier si le formulaire existe et est valide ensuite Submit, mais renvoie false. C'est comme ci-dessous:

 function ValidateForm(submit) { var form = $('form'); // if form doesn't exist on the page - return true and continue if (typeof form[0] === "undefined") return true; // now check for any validation errors if (submit) { if (!$(form).valid()) { return false; } else { $(form).submit(); } } else { return true; } return true; } 

Ma spéculation est que form.submit se déclenche comme il se doit, mais depuis que le soumission prend un peu plus de temps pour finir, il continue avec le prochain bloc de code dans l'événement button onclick .

J'ai d'abord pensé que ce problème était C # comme dans le POST. Je sauvegarde un gros morceau de données avec quelques boucles, et tout bloc de code qui est lourd, j'ai cette partie dans

 var saveTask = Task.Factory.StartNew(() => ControllerHelper.SomeMethod(db, model)); Task.WaitAll(saveTask); 

WaitAll attendra et mettra en pause l'exécution jusqu'à ce que SomeMethod finisse son exécution. Je ne sais pas comment puis-je verrouiller un processus en javascript et attendre qu'il termine l'exécution. Parce que je pense que si je peux en quelque sorte verrouiller le formulaire.submit () dans ValidateForm jusqu'à son traitement fini … via une méthode de rappel peut-être …

S'il vous plaît, si quelqu'un peut me mettre dans la bonne direction, j'apprécierais grandement l'aide. Si vous avez besoin de plus d'informations, faites-le moi savoir que je serais ravi de vous fournir!

Modifier la promesse de retour anti pattern

Alors que jfriend00 a commenté la façon dont la réponse originale renvoie la promesse est anti-modèle, une meilleure façon serait:

 function ValidateForm(){ // do your logic if (pass) { return $.post("urlToPost"); else { return $.Deferred().reject(xxx).promise(); } } 

Plus d'informations sur ceci, cocher https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns

Réponse originale

Je vais essayer d'imaginer votre problème:

Ce que vous voulez, c'est exécuter ValidateForm premier, quand il est passible (de sorte que lorsque le formulaire post est terminé), puis faites MoveNext

Votre problème est, MoveNext est appelé avant que ValidateForm soit terminé.

Si je suis correct, la raison en est parce que Javascript par nature est une programmation asynchrone, donc utilisez un rappel pour tirer lorsque quelque chose a été fait.

Donc, dans votre situation, vous devez utiliser la promesse de l'achever.

Essentiellement, ce que vous devez faire, c'est:

  1. Laisser ValiateForm prometteur
  2. MoveNext simplement MoveNext une fois que ValidateForm a fini

Donc le code serait comme:

 function ValiateForm(){ var dfd = jQuery.Deferred(); // do your logic if(pass){ $.post("urlToPost" } else { // also failed dfd.reject(); } // return the promise return dfd.promise(); } 

Alors votre prochain bouton de déplacement serait comme

 $('button').on('click', function () { if (this.id === "btnMoveToNextTab") { $.when(window.ValidateForm(true)).then(function(){ // after success post form $.ajax({ url: url, context: { param: 'next' }, method: "GET", data: data, success: function(response) { if (typeof response == 'object') { if (response.moveAhead) { MoveNext(); } } else { $('#mainView').html(response); } ScrollUp(0); } }); if (this.id === "btnMoveToPreviousTab") { MoveBack(); } } return false; }); }); 

Plus d'informations sur la caisse de promesse

https://api.jquery.com/deferred.promise/

Et pour courir quand finir

https://api.jquery.com/deferred.then/

Je publie ceci, c'est une note pour Alan puisque c'est un code multi-lignes et je ne peux pas le rendre lisible dans un commentaire. Pour éviter la promesse anti-pattern lorsque vous exécutez parfois une opération asynchrone et parfois pas, vous pouvez l'utiliser:

 function ValidateForm(){ // do your logic if (pass) { return $.post("urlToPost"); else { return $.Deferred().reject(xxx).promise(); } } 

De cette façon, vous êtes toujours de retour une promesse. Dans un cas, la promesse provient de $.ajax() . Dans l'autre cas, vous revenez simplement d'une promesse rejetée puisque l'opération a déjà échoué.