Synchronous VBscript changé en Javascript asynchrone incorrectement [duplicate]

Oct 09 2020

Mon patron m'a donc demandé d'examiner un problème où ils portaient d'anciens scripts VBscript dans des scripts Javascript, mais où le Javascript avait un flux de programme incorrect. Le seul problème est que j'ignore vraiment les deux, mais si votre patron vous le demande, alors vous devez faire un plan. ;-)

Dans le VBscript, l'utilisateur avait le choix et si "Non", l'écran / la vue suivante ne s'affichait pas. Cependant, avec le Javascript, l'écran / vue suivant est chargé indépendamment du fait que l'utilisateur choisisse "Non / Annuler" ou non. Cela ne devrait pas arriver.

Voici le VBscript, la partie importante se situe entre le //:

vEffectiveDate  = ScreenForm("smoke.Effective Date").Value
vLastRunDate    = ScreenForm("smoke.Last Run Date").Value
sStatus         = ScreenForm("smoke.Calc Status").Value

vMsg = ""

If Len(sStatus) = 0 Then
    sStatus = "SUCCESFUL"
    ScreenForm("smoke.Calc Status").Value = sStatus
End If

If Len(vEffectiveDate) > 0 Then

    If Not IsDate(vEffectiveDate) Then 
        vMsg = vMsg & "[Effective Date] Is not a date." & Chr(13)
    
    ElseIf cdate(vEffectiveDate) <= cdate(vLastRunDate) Then
        vMsg = vMsg & "[Effective Date] cannot be on/before " & vLastRunDate &"." & Chr(13)
    End IF

End If

//////////////////////////////////////////////////////////////////////////////
If UCASE(sStatus) <> "SUCCESFUL" Then
    sResponse = MsgBox ("Forecast calculation still busy. Results might not be accurate. Continue?", (vbYesNo), "WARNING")
    If sResponse = vbNo Then
        MsgBox cstr("Screen will refresh. Please click on Update to try again."), (vbOKOnly), "INFORMATION"
        ScreenForm("smoke.Calc Status").Value = "REFRESH"
        'msErr = "ABORT"
    End If
End If
//////////////////////////////////////////////////////////////////////////////

If vMsg <> "" Then
MsgBox (vMsg)
msErr = "ERROR"
End If

Voici le Javascript, la partie importante se situe entre le //:

 var vEffectiveDate="";
var vLastRunDate="";
var sStatus="";
var vMsg="";
var sResponse="";
vEffectiveDate = document.getElementById("Smoke.Effective Date").value;
vLastRunDate = document.getElementById("Smoke.Last Run Date").value;
sStatus  = document.getElementById("Smoke.Calc Status").value;
vMsg = "";
if ((sStatus).length == 0  ){
    sStatus = "SUCCESFUL";
    document.getElementById("Smoke.Calc Status").value= sStatus;
}
if ((vEffectiveDate).length > 0  ){
    if (!isDate(vEffectiveDate)  ){
        vMsg = vMsg+"[Effective Date] Is not a date." + ";\r\n";
    } else if (  moment( toDate(vEffectiveDate)).isBefore(toDate(vLastRunDate)) ){
        vMsg = vMsg+"[Effective Date] cannot be on/before "+vLastRunDate+"." + ";\r\n";
    }
}
///////////////////////////////////////////////////////////
if ((sStatus).toUpperCase() != "SUCCESFUL"  ){
 $.confirm({title: "Confirmation",columnClass: 'col-md-6 col-md-offset-3', content:"Forecast calculation still busy. Results might not be accurate. Continue?", buttons: {confirm: function() { sResponse= 1;}, cancel: function() {sResponse= 2;return;}}}); if (sResponse == 2 ){ $.alert({title:  "INFORMATION",columnClass: 'col-md-6 col-md-offset-3', content:("Screen will refresh. Please click on Update to try again.").toString(),});
        document.getElementById("Smoke.Calc Status").value= "REFRESH";
  msErr = "ABORT";
    }   
}
//////////////////////////////////////////////////////////


if (vMsg != ""  ){
$.alert({title: 'Validation Message',columnClass: 'col-md-6 col-md-offset-3', content:(vMsg),});
msErr = "ERROR";
}

Donc, j'ai vu qu'il existe un concept async-await-promises en Javascript, mais il semble qu'il n'est pas pris en charge par Internet Explorer , et nous devons garder à l'esprit que certains de nos utilisateurs utilisent encore IE ... soupir ... Il semble donc que je ne pourrai pas utiliser un concept d'attente asynchrone, pas que je sois sûr que ce serait nécessaire dans cette situation.

Ensuite, j'ai également lu ici à propos d'un bouton d'envoi pour un formulaire , et que cela pourrait aussi être mon problème?

Je suis tellement ignorant de Javascript que je ne sais même pas comment changer le comportement par défaut du bouton si tel est le problème.

J'apprécierais que quelqu'un m'aide dans la bonne direction pour que je puisse apprendre et grandir.

Réponses

1 trincot Oct 09 2020 at 19:58

En effet, la deuxième partie du code (avec l'alerte) est exécutée quel que soit le résultat de l'invite de confirmation.

La principale différence avec $.confirmet VBA MsgBoxest que cela MsgBoxbloque la poursuite de l'exécution du code, alors que $.confirmcela ne le fait pas. Cela signifie donc que le code qui le suit (la if (sResponse == 2)partie), est exécuté immédiatement. À ce moment-là, aucune modification n'a été apportée à sResponse(car aucun bouton n'a été cliqué), donc cela arrive trop tôt.

Cependant, $.confirmaccepte certaines fonctions en tant qu'arguments, qui seront appelés lorsqu'un bouton est enfoncé dans le popup. En fait, votre code passe déjà de telles fonctions, mais elles ne font rien d'autre que la configuration sResult. Vous devez donc déplacer la deuxième partie du code (avec l'alerte) dans une telle fonction.

Commençons par formater un peu votre code pour qu'il devienne plus lisible, et vous pourrez mieux repérer ces fonctions de rappel:

if ((sStatus).toUpperCase() != "SUCCESFUL") {
    $.confirm({
        title:  "Confirmation",
        columnClass: 'col-md-6 col-md-offset-3', 
        content:"Forecast calculation still busy. Results might not be accurate. Continue?",
        buttons: {
            confirm: function() {
                // This executes when button is clicked
                sResponse= 1;
            },
            cancel: function() {
                // This executes when button is clicked
                sResponse= 2;
                return;
            }
        }
    });
    // This executes immediately (without waiting for button click)
    if (sResponse == 2  ){
        $.alert({ title: "INFORMATION", columnClass: 'col-md-6 col-md-offset-3', content:("Screen will refresh. Please click on Update to try again.").toString(), }); document.getElementById("Smoke.Calc Status").value= "REFRESH"; msErr = "ABORT"; } } // Also this executes too early when confirm was executed: if (vMsg != ""){ $.alert({
        title: 'Validation Message',
        columnClass: 'col-md-6 col-md-offset-3',    
        content:(vMsg),
    });
    msErr = "ERROR";
}

J'ai ajouté des commentaires pour montrer où se trouvent les parties importantes du code.

Maintenant, déplacez cette deuxième partie dans la fonction de rappel qui se rapporte à la réponse n ° 2:

if (sStatus.toUpperCase() != "SUCCESFUL") {
    $.confirm({ title: "Confirmation", columnClass: 'col-md-6 col-md-offset-3', content:"Forecast calculation still busy. Results might not be accurate. Continue?", buttons: { confirm: function() { sResponse= 1; processMessage(); // <--- added this }, cancel: function() { sResponse= 2; // Moved code here, as it needs to execute when Cancel is clicked $.alert({
                    title: "INFORMATION",
                    columnClass: 'col-md-6 col-md-offset-3',
                    content: "Screen will refresh. Please click on Update to try again.",
                    // Code that should execute when alert is closed:
                    onAction: function () {
                        document.getElementById("Smoke.Calc Status").value= "REFRESH";
                        msErr = "ABORT";
                        processMessage(); // <--- added this
                    }
                });
            },
        }
    });
} else { // <-- added
    processMessage();
}

function processMessage() {
    // Moved code in a function, as it should only execute after confirm/alert is closed 
    if (vMsg != "") {
        $.alert({
            title: 'Validation Message',
            columnClass: 'col-md-6 col-md-offset-3',    
            content: vMsg,
        });
        msErr = "ERROR";
    }
}

Je n'ai pas testé ce code, car il a des dépendances que je ne connais pas.