Attivazione di eventi personalizzati in callback AJAX

7

Sono abbastanza nuovo su JavaScript, ma una delle cose che è stata frustrante è che i nostri callback AJAX si sono arricchiti di diverse funzionalità, rendendo difficile mantenere tutto separato e organizzato.

Sono davvero nuovo alla programmazione, ho l'impressione che l'apprendimento di MVC mi aiuterebbe un po 'di più, ma per ora usare eventi personalizzati sembra che potrebbe aiutarmi a mantenere il mio codice molto più pulito e prevenire alcuni problemi. Ecco di cosa sto parlando:

function myAjaxFunctionThatGetsTestData(){
    $.post('ajax/test.html', function(data) {
        $(document).trigger('testDataLoaded',data);
    });
}

function myOtherFunctionThatsDependentUponAjax(){
    getSomeTestData(); //start process of retrieving the data from ajax
    //then let me know when data has been retrieved
    $(document).one('testDataLoaded', function(data){
        alert (data);
    }
}

function getSomeTestData(){
    //maybe data was already retrieved by a different module, so check first
    if (data){
        $(document).trigger('testDataLoaded',data); 
    }
    else{
        myAjaxFunctionThatGetsTestData(); 
    }
}

Inoltre non so se va bene che sto attivando un documento o meno ...

Ci sono degli schemi che assomigliano a questo di cui posso leggere di più? Quali sono i potenziali problemi con questo?

    
posta Sabrina Gelbart 28.02.2012 - 13:48
fonte

6 risposte

3

Questo è chiamato Bus Eventi ed è un modo molto utile per disaccoppiare il tuo codice quando non vuoi che ogni post AJAX (o qualsiasi altra azione in tal senso) debba esplicitamente indica cosa deve succedere di conseguenza.

// We've consolidated this functionality in an event manager, which gives us more power
// to log and recover from errors in event handlers.
EventManager.subscribe('ContentAdded', function(e) {
    // color every other row whenever content is added to the DOM.
    $('table.grid>tbody>tr:nth-child(even)', e.Content).addClass('even-row');
});

Nota come posso pubblicare questo evento ovunque io desideri nel codice, e nessuno di quei posti deve essere a conoscenza di questo codice. Posso anche gestire l'evento ovunque desideri, senza essere strettamente collegato al codice di pubblicazione.

Nel progetto (ASP.NET MVC) su cui lavoro, abbiamo trovato che questo approccio è così efficace che abbiamo quasi eliminato qualsiasi altro tipo di chiamate AJAX. Abbiamo il nostro framework basato sugli eventi al punto in cui la maggior parte dei nostri collegamenti AJAX utilizza un unico gestore di callback globale che pubblica semplicemente gli eventi restituiti dal server. Qualsiasi modulo interessato a ricevere notifiche quando si verificano eventi specifici può iscriversi a questi eventi a livello globale.

Potrei creare un collegamento usando un codice come questo:

@Html.EventAction("Create Task", "CreateTask")

... che il mio framework può rendere come HTML in questo modo:

<a href="/.../CreateTask" data-ajax="true" data-ajax-success="EventHandlers.Success">
    Create Task
</a>

Quando l'utente fa clic su questo link, viene sequestrato per eseguire una richiesta AJAX a un'azione come questa:

public ActionResult CreateTask()
{
    if(!UserCanCreateTasks())
        return Events.ErrorResult("You don't have rights to create tasks.");

    Events.OpenModalDialog("Create Task", "TaskEditView", new TaskEditViewModel());
    return Events.Result();
}

Ciò genererebbe a sua volta un oggetto JSON con un ModalDialogOpenedEvent , che include i contenuti di rendering della finestra di dialogo.

Il metodo EventHandlers.Success pubblicherà semplicemente tutti gli eventi che ritornano, causando indirettamente un gestore come questo da invocare:

EventManager.subscribe('ModalDialogOpenedEvent', function(e) {
    createDialog(e.Title, e.Contents);
});

Quindi la nostra logica di controllo può effettivamente rimanere nel nostro controller e abbiamo ridotto drasticamente la quantità di javascript personalizzati che dobbiamo scrivere per una determinata funzionalità. Non è più necessario scrivere codice del gestore personalizzato per ogni tipo di pulsante nella nostra interfaccia utente e non dobbiamo preoccuparci di ciò che accade quando il server restituisce una risposta che non ci aspettavamo.

Ad esempio, se la sessione dell'utente è scaduta, il codice azione non verrà nemmeno richiamato: il server reindirizzerà immediatamente la richiesta AJAX a un gestore di accesso. Abbiamo scritto il gestore di accesso per essere abbastanza intelligente da rilevare se si tratta di una richiesta AJAX event-driven e restituire un evento che causa l'apertura di una finestra di dialogo di accesso. La richiesta che l'utente stava tentando di eseguire viene salvata fino a quando il server non restituisce un evento per indicare che l'accesso è riuscito e quindi viene ritentato automaticamente. Puoi immaginare quanto codice extra richiederebbe se ogni richiesta AJAX nel nostro sistema dovesse essere pronta a gestire questo tipo di caso angolare. Ma con un sistema basato su eventi, è un gioco da ragazzi.

    
risposta data 14.06.2012 - 04:57
fonte
2

Se non ho frainteso la tua domanda, stai facendo qualcosa del genere (con jQuery):

// Bind to some arbitrary event name
$("body").bind("arbitrary", function(evt){
  alert("o/");
});

// Create a random event
var e = jQuery.Event("arbitrary");

// Fire the event
$("body").trigger(e);

... e chiedendo se è ok. È una tecnica comune, utilizzata in binari , ad esempio. Inoltre, jQuery offre a questi eventi un bel set di proprietà con cui giocare. Non vedo alcun problema con l'associazione a "documento".

    
risposta data 18.06.2012 - 21:56
fonte
1

cercherò di rispondere alla tua domanda. Penso che cosa sta succedendo qui è che i tuoi metodi AJAX sono impostati per ottenere dati in modo asincrono quindi quando provi e usi la variabile data non è impostata perché la chiamata AJAX viene ancora eseguita in background. Quello che devi fare è impostare la tua chiamata ajax in modo che non sia asincrona ma sincrona, quindi il tuo codice attenderà fino a quando la chiamata AJAX non sarà completata prima di passare.

usa il plugin Firebug per FireFox per eseguire il debug del tuo codice Javascript, ti aiuterà a capire come funziona AJAX e molto altro ancora sull'uso della libreria jQuery.

aggiorna questo metodo:

function myAjaxFunctionThatGetsTestData(){
   $.post('ajax/test.html', function(data) {
    $(document).trigger('testDataLoaded',data);
   });
}

A:

function myAjaxFunctionThatGetsTestData(){
   $.ajax({
    type: "POST",
    dataType: "html",
    url: "ajax/test.html",
    data: "",
    async: false, //by default all AJAX calls are set to true
    contentType:  "text/html",
    success: function(data){
     //successful call to server side and back
     //add data to you _data global variable
     //or do your data check here
     _data = data;
    },
    error: function(jqXHR, textStatus, errorThrown){
     //display error message, ajax call failed
     alert(textStatus);
    }
   });
}
    
risposta data 18.06.2012 - 22:50
fonte
0

Idealmente vuoi collegare i tuoi gestori di eventi a ciò che riguardano. Nell'applicazione più grande può essere un oggetto dispatcher o un oggetto che gestisce la comunicazione tra oggetti javascript.

In un caso più semplice, come legare specifici elementi dell'interfaccia utente, puoi semplicemente associarli a essi, in questo modo quando lo imposti o lo fai scattare, sai che l'elemento con cui si relaziona. O un elemento radice se l'elemento UI fa parte di un widget.

Altrimenti non penso ci sia alcun problema con l'utilizzo dell'elemento documento in quanto tale, forse è meglio usare il triggerHandler () dipende invece se vuoi semplicemente attivare una funzione o emettere un oggetto evento completo.

    
risposta data 15.04.2012 - 00:13
fonte
0

Probabilmente questo è jquery, che purtroppo modifica il modo in cui scrivi codice per più php-ish come.

Normalmente quando si usano mootools, impacchettare la chiamata e i gestori in un oggetto. Ad esempio.

function edit_handler(a,b,c)
{

    var that = this; //priv member
    this.onProcess = function(data) {}; //public member
    this.onOk = function() {};
    this.onFailure = function() {};

    function process(data) // priv method
    {
        that.onProcess();
        //do processing
    }

    this.run = function (param) //public method
    {
        AJAX.call => onSuccess => process(ret) ; onFail => that.onFailure();
    }

}

var edit_amount = new edit_handler(1,2,3);
edit_amount.onFailure = function() {alert("Update failed");}
form field=> on edit => edit_amount.process(value);

Il mio punto: usa oggetti e metodi / proprietà private. Fare molte funzioni è sempre creare confusione.

    
risposta data 15.04.2012 - 03:41
fonte
0

Ecco una versione semplificata di ciò che stai cercando di fare. Ed è molto più facile da seguire:

function myAjaxFunction(){
    $.post('ajax/test.html', function(data) {
        myOtherFunctionThatsDependentUponAjax(data);
    });
}

function myOtherFunctionThatsDependentUponAjax(){
    alert(data);
}

Questo dovrebbe anche essere possibile, anche se sono incerto sugli idiomi di JQuery:

function myAjaxFunction(){
    $.post('ajax/test.html', myOtherFunctionThatsDependentUponAjax);
}

function myOtherFunctionThatsDependentUponAjax(){
    alert(data);
}
    
risposta data 14.06.2012 - 04:52
fonte