Domanda

Ho un'applicazione Web basata su Apache, PHP, JS / JQuery. Un modulo dell'applicazione viene inizializzato quando il documento è caricato. Quella sequenza chiama un init () funzioni che esegue un numero di compiti, tra gli altri, recupera due finestre di dialogo HTML tramite Ajax e li inserisce nella pagina esistente. Un riferimento a quei dialoghi viene salvato come variabili, in modo da non dover specificare i selettori jQuery in tutti i miei script, ma possono semplicemente utilizzare quelle variabili. Questo funziona bene, tranne che ci sono pochissimi casi (ad ora e poi ...) quando le variabili sono "indefinite" quando si tenta di associare un gestore a un elemento all'interno delle finestre di dialogo recuperato. Che è dispari, perché a parte quella legame le finestre di dialogo sono utilizzabili durante tutta l'applicazione. Ciò suggerisce che le chiamate Ajax riescono, ma in modo appariscente c'è qualche tipo di condizione di gara, in modo che ora e poi le variabili siano impostate solo dopo il tentativo del bind.

Nella mia comprensione questo non dovrebbe accadere, poiché il bind è fatto nella parte .done () () parte di A quando () e dovrebbe essere eseguita solo dopo che il recupero Ajax delle finestre di dialogo è terminato all'interno di quando ().

Apartivamente mi manca qualcosa di fondamentale qui. Qualcuno ha un suggerimento per me?

I seguenti escritti di codice citano dall'attuazione lavorativa. Possono apparire sintatticamente non validi come alcune parti, ma ciò è solo dovuto alla rimozione delle parti di codice non pertinenti qui. Il codice unsorniato funziona bene.

Le variabili:

Shorty.Tracking.Dialog.List:{};
Shorty.Tracking.Dialog.Click:{};
.

La sequenza di inizializzazione:

$(window).load(function(){
  //...
  var dfd = new $.Deferred();
  $.when(
    // load layout of dialog to show the list of tracked clicks
    Shorty.Tracking.init()
  ).done(function(){
    // bind actions to basic buttons
    Shorty.Tracking.Dialog.List.find('#close').on('click',function(){
      // ...
    });
    // ...
  });
  // ...
})
.

La funzione Init abbreviata:

Shorty.Tracking.init:function(){
    // ...
    var dfd=new $.Deferred();
    // two dialogs are used by this plugin
    var dialogs={
      'list':  Shorty.Tracking.Dialog.List,
      'click': Shorty.Tracking.Dialog.Click
    };
    // load dialogs from server
    $.each(['list','click'],function(i,dialog){
      if (...){
        // ...
        dfd.resolve();
      }else{
        // load dialog layout via ajax and create a freshly populated dialog
        $.ajax({
          type:     'GET',
          url:      OC.filePath('shorty-tracking','ajax','layout.php'),
          data:     { dialog: dialog},
          cache:    false,
          dataType: 'json'
        }).pipe(
          function(response){return Shorty.Ajax.eval(response)},
          function(response){return Shorty.Ajax.fail(response)}
        ).done(function(response){
          // create a fresh dialog
          // insert it alongside the existing dialogs in the top controls bar
          $('#controls').append(response.layout);
          switch (dialog){
            case 'list':
              Shorty.Tracking.Dialog.List=$('#controls #shorty-tracking-list-dialog').first();
              break;
            case 'click':
              Shorty.Tracking.Dialog.Click=$('#controls #shorty-tracking-click-dialog').first();
          } // switch
          dfd.resolve();
        }).fail(dfd.reject)
      } // else
    }); // each
    return dfd.promise();
  },
.


.

Con la risposta di BERGI sono riuscito a rimuovere apparentemente il problema originale. Fino ad ora non ho potuto rilevare alcun tentativo più fallito vincolante. Tuttavia non potevo seguire completamente quel suggerimento: nella sua risposta ha suggerito di rimuovere l'istruzione Switch nel metodo di inizializzazione a favore di un incarico diretto. Questo certamente è molto più elegante, ma questo non funzionerà. Ho l'impressione che ci sia un po 'di missinderstanding dalla mia parte su come JavaScript gestisce i riferimenti e / o le funzioni memorizzate in variabili.

Forse tu, Bergi, o qualcun altro può gettare qualche spiegazione di luce su questo:

Questo è il metodo di inizializzazione modificato dall'alto:

  init:function(){
    if (Shorty.Debug) Shorty.Debug.log("initializing tracking list");
    // check if dialogs already exist
    if (   $.isEmptyObject(Shorty.Tracking.Dialog.List)
        && $.isEmptyObject(Shorty.Tracking.Dialog.Click) ){
      // two dialogs are used by this plugin
      var dialogs={
        'list':  Shorty.Tracking.Dialog.List,
        'click': Shorty.Tracking.Dialog.Click
      };
      // load dialogs from server
      var dfds=$.map(dialogs,function(obj,dialog){
        // load dialog layout via ajax and append it to the collection of dialogs in the controls
        return $.ajax({
          type:     'GET',
          url:      OC.filePath('shorty-tracking','ajax','layout.php'),
          data:     { dialog: dialog},
          cache:    false,
          dataType: 'json'
        }).pipe(
          function(response){return Shorty.Ajax.eval(response)},
          function(response){return Shorty.Ajax.fail(response)}
        ).done(function(response){
          // create a fresh dialog and insert it alongside the existing dialogs in the top controls bar
          $('#controls').append(response.layout);
//           obj=$('#controls #shorty-tracking-'+dialog+'-dialog').first();
          switch(dialog){
            case 'list':
              Shorty.Tracking.Dialog.List=$('#controls #shorty-tracking-list-dialog').first();
              break;
            case 'click':
              Shorty.Tracking.Dialog.Click=$('#controls #shorty-tracking-click-dialog').first();
              break;
          } // switch
        })
      }) // map
      return $.when.apply(null, dfds);
    }else{
      // dialogs already loaded, just clean them for usage
      Shorty.Tracking.Dialog.List.find('#list-of-clicks tbody tr').remove();
      new Deferred().resolve();
    } // else
  },
.

Nel mezzo si vede la dichiarazione di assegnazione commentata e attualmente sostituita dalla dichiarazione di commutazione di seguito. Ho provato diverse varianti, come obj.element e così via ma fallì. Al di fuori della funzione le variabili shorty.tracking.dialog.list e shorty.tracking.-dialog.Click Restare vuoto.

Sono un newbie assoluto al Web Stuff ANS JS / JQuery. Ma sono certamente curioso di saperne di più su questo modo di gestire i riferimenti.

È stato utile?

Soluzione

Questo è il codice problematico:

var dfd=new $.Deferred();
$.each(['list','click'], function(){
    ...
    dfd.resolve/fail();
});
.

La crei solo una differita, ma risolvela più volte. Quindi, quando avviene la prima risoluzione, il secondo Ajax non sarebbe stato finito.

Allora, usa invece due differiti e combinarli attraverso jQuery.when() . Inoltre, non penso che avrai bisogno di creare differiti da solo. Basta prendere quei due che ottieni dalle chiamate pipe().

function init() {
   var dialogs={
      'list':  Shorty.Tracking.Dialog.List,
      'click': Shorty.Tracking.Dialog.Click
   };
   var deferreds = $.map(dialogs, function(obj, dialog) {
       return $.ajax(...).pipe(...).done(...
           // really, don't use switch here:
           obj.element = response.layout;
       }); // done() returns the Deferred
   });
   return $.when.apply(null, deferreds);
}

...

$.ready(function($) {
    init().done(...);
});
.


.

OK, ho bisogno di spiegare la dichiarazione di commutatore. È vero, i valori nell'oggetto dialogs verranno assegnati da variabili [non ètilizzate] e tenere premuto quel valore (undefined), quando i campi vengono riassegnati i valori Shorty non cambieranno. Non ci sono "puntatori" in JavaScript. Pensavo solo che sarebbe stato utile usare la variabile attuale dialog in un operatore membro, invece di un'istruzione Switch. Per assegnare a Shorty.Tracking.Dialog.List e .Click, è necessario utilizzare qualcosa come

var dialogs = ["list", "click"];
var shortcut = Shorty.Tracking.Dialog; // some object
for (var i=0; i<dialogs.length; i++) {
    // loop over them,
    // do the ajax stuff
    var element = $(repsonse.layout); // get the added element from the response
    $('#controls').append(element);

    shortcut[dialogs[i]] = element;
}
.

(Alla fine utilizzare uno snippet da Come faccio a fare la prima lettera di una stringa maiuscola in JavaScript? ) .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top