postSubmit and SubmitSuccess events can block each other

postSubmit and SubmitSuccess events can block each other

rf1234rf1234 Posts: 2,801Questions: 85Answers: 406
edited August 2018 in Editor

@allan
I had used both Editor events "postSubmit" and "submitSuccess" in parallel in one of my rather complex Editor instances. The tasks in the "postSubmit" actually were only executed on successful execution as well because I checked for errors. I had implemented this logic because before Editor 1.7 it was not possible to check for "action" in the submitSuccess event.

This caused very serious errors: After only a few user actions my screen froze and there were absolutely no error messages. It took me weeks of experimenting to finally find the solution: I got rid of the postSubmit event and moved all of the tasks into the submitSuccess event handler which works because I can chek for "action" there now, too.

The problem disappeared!

Question: Is there any way to detect conflicting event handlers more easily? There were no error messages ...

Thanks!
Roland

Answers

  • allanallan Posts: 61,431Questions: 1Answers: 10,048 Site admin

    Hi Roland,

    That's really odd! They shouldn't conflict at all. Even if you were to use postSubmit to modify the original JSON returned from the server, that shouldn't make any difference to submitSuccess. Only if they were performing async actions should there be any possibility of issues.

    Are you able to give me a page showing the issue so I can trace it through?

    Thanks,
    Allan

  • rf1234rf1234 Posts: 2,801Questions: 85Answers: 406

    I can show you what I had before and what I have now:

    This is what I had before:

    contractEditor
        .on( 'submitSuccess', function( e, json, data, action ) {          
          setTimeout(function(){
               destroyObjects([contractEditor, contractDescriptionEditor, contractCommentsEditor, contractTable]);
               showContractTable();
           }, 200);                
           ajaxReloadTbls( [contractGovCreditorTable] );
       })
       .on( 'postSubmit', function ( e, json, data, action ) {
           if (! json.error && ! json.fieldErrors) {              
               if ( action === 'remove' ) {
                   $('#tblCashFlowContainer, #tblFixedContainer, #tblVariableContainer').addClass("hidden");
               }
               if ( action === 'remove' || action === 'edit') {
                   $.ajax({
                       type: "POST",
                       url: 'actions.php?action=processCounterTrade',
                       data: {
                           table: 'contract',
                           id: 0,
                           contractId: contractIdSelected,
                           action:     action,
                           updateElement: 1, // the element was changed
                           updateCashflows: 0 //cashflows weren't changed
                       }
                   });
               }
           }
       });
    

    This is what I have now:

    contractEditor
       .on( 'submitSuccess', function( e, json, data, action ) {                
           setTimeout(function(){
               destroyObjects([contractEditor, contractDescriptionEditor, contractCommentsEditor, contractTable]);
               showContractTable();
           }, 200);                
           ajaxReloadTbls( [contractGovCreditorTable] );
           if ( action === 'remove' ) {
               $('#tblCashFlowContainer, #tblFixedContainer, #tblVariableContainer').addClass("hidden");
           }
           if ( action === 'remove' || action === 'edit') {
               $.ajax({
                  type: "POST",
                   url: 'actions.php?action=processCounterTrade',
                   data: {
                       table: 'contract',
                       id: 0,
                       contractId: contractIdSelected,
                       action:     action,
                       updateElement: 1, // the element was changed
                       updateCashflows: 0 //cashflows weren't changed
                   }
               });
           }
       })
    
    

    Unfortunately I cannot set this up for you again. This is only a small part of a fairly complex page. That's why it took me so long to figure this out. The JavaScript file containing just the Editor instances and the data tables on the page is 3,300 lines long - and this doesn't include the functions for rendering, making field dependencies work etc.

    My lesson learned is: Try to avoid using submitSucces and postSubmit in parallel. And if you need to do it do it in a mutually exclusive way. In this example either the tasks on submitSuccess or the tasks on postSubmit are executed but not both at the same time.

    userEditor
        .on('postSubmit', function (e, json, data, action) {
            if (json.error) {
                if ( json.error.indexOf('1062 Duplicate entry') >= 0 ) {
                    json.error = lang === 'de' ? 
                                "Es tut uns Leid. Diese E-Mail-Adresse wird \n\
                                 schon verwendet. Bitte geben Sie eine andere \n\
                                 ein." : 
                                "Sorry this email address is already in use. \n\
                                 Please enter a different one."; 
                }
            }
        })
        .on( 'submitSuccess', function () {
            ajaxReloadTbls( [userTable, userPhoneTable, userAddressTable, userSecTable,
                             userGovDeptTable, userCreditorTable, userLogTable] );
    })
    

    But is there any way how I could figure out myself if things are blocking each other in JavaScript? I have no idea how to do this unfortunately.

  • allanallan Posts: 61,431Questions: 1Answers: 10,048 Site admin

    Right - the combination of async actions bothers me. I don't believe that there is any issue with using postSubmit and submitSuccess together. Indeed, all of the Editor events are synchronous, so there should never be a conflict between any of them.

    What bothers me about the code you are using is:

    1. You trigger a setTimeout for 200mS - that appears to destroy the existing Editor and DataTable, then create a new one.
    2. Then ajaxReloadTbls which happens before those 200mS have elapsed. How long that takes to execute will depend on network latency. It might take 190mS, it might take 210mS, or some other amount of time.
    3. Then Editor does its stuff for updating the table - that should happen within 200mS, but it has to be considered that it might take longer.
    4. If you are using server-side processing, that's another async behaviour that needs to be taken account of when drawing the table.

    I don't think that using postSubmit and submitSuccess together is an issue. You are running into timing issues with multiple async "threads" happening.

    Allan

  • rf1234rf1234 Posts: 2,801Questions: 85Answers: 406
    edited August 2018

    Anyway, I got my problem solved and I am more careful now. The "destroy and create new" activities were part of my attempts to get this resolved. Didn't really help very much. But I am keeping this for now because I am scared to make changes to this stuff again. The ajaxReload of this other table is not conflicting because that data table is fully independent of the ones that I destroy.
    I am not using server-side processing here at all.

This discussion has been closed.