Domanda

Al momento non stiamo utilizzando alcun framework serio lato client oltre a jQuery (e jQuery.ui + convalida + plug-in per la procedura guidata dei moduli).

Un problema che emerge alcune volte nel nostro codice è questo:

  1. Abbiamo un pulsante che avvia una chiamata Ajax al server.
  2. Durante la chiamata, viene visualizzata un'icona di "caricamento" con del testo
  3. Se il server restituisce un risultato troppo rapidamente (ad esempio <200 ms), "dormiamo" per 200 millisecondi (utilizzando setTimeout()), per evitare lo sfarfallio dell'icona e del testo in attesa .
  4. Dopo max(the call returns, a minimal timeout), cancelliamo l'icona e il testo di caricamento.
  5. Quindi viene visualizzato un testo di errore, se si è verificato un problema nella chiamata ajax (il server non restituisce 500, ma un json personalizzato che ha una proprietà "messaggio di errore". In effetti, a volte abbiamo un proprietà nella risposta per campo modulo ... e quindi abbiniamo gli errori ai campi modulo ... ma sto divagando).
  6. In caso di successo, facciamo ... qualcosa (dipende dalla situazione).

Sto cercando di ridurre al minimo il riutilizzo del codice e di scrivere o riutilizzare un modello / pezzo di codice / framework che lo faccia. Anche se probabilmente non inizierò a utilizzare un intero nuovo framework per impieghi gravosi solo per questo caso d'uso, mi piacerebbe comunque sapere quali sono le mie opzioni ... forse un simile framework lato client sarebbe buono anche per altre cose. Se esiste un framework leggero che non richiede di capovolgere tutto il mio codice e potrei usarlo solo in casi specifici, allora potremmo effettivamente usarlo invece di reinventare la ruota.

Ho appena sentito parlare di Ember.js : è adatto per risolvere questo problema? Come risolveresti?

È stato utile?

Soluzione

$(function(){
 var buttonSelector = "#button";
 $('body').on({'click': function(evt){
    var $button = $(this);
    $button.toggleClass('loading');
    var time = new Date();
    $.get('some/ajax').then(function(data,text,jqXhr){
   // typical guess at load work
       $button.empty();
       $(data).wrap($button);
    }).fail(function(data,text,jqXhr){
     alert("failed");
    }).done(function(data,text,jqXhr){
       var elapsed = new Date();
      if((elapsed - time) < 200){
        alert("to short, wait");
      }
      $button.toggleClass('loading');
    });
  }},buttonSelector,null);
});

Altri suggerimenti

Racchiudi $ .ajax nella tua funzione.in questo modo puoi implementare il tuo accodamento, ecc. Suggerirei di fare un componente jquery per questo.Può diventare piuttosto potente, ad esempio puoi anche passare intestazioni http, ecc.
Per quanto riguarda i framework dipende dalle vostre esigenze.
Ad esempio, potresti considerare Kendo UI, ha un buon framework per la creazione di origini dati: http://demos.kendoui.com/web/datasource/index.html .

Codice di esempio funzionante (beh, quasi)

Comunque stavo cercando qualcosa sulla falsariga della risposta di @ DefyGravity: la sua idea è buona, ma è ancora pseudo-codice / non del tutto completa.Ecco il mio codice funzionante ( demo quasi funzionante , fino all'URL Ajax stesso e modifiche dell'interfaccia utente)

Il codice e l'esempio di utilizzo:

jQuery.fn.disable = function() {
    $(this).attr("disabled", "disabled");
    $(this).removeClass("enabled");

    // Special handling of jquery-ui buttons: http://stackoverflow.com/questions/3646408/how-can-i-disable-a-button-on-a-jquery-ui-dialog
    $(this).filter("button").button({disabled: true});
};
jQuery.fn.enable = function() {
    $(this).removeAttr("disabled");
    $(this).addClass("enabled");
    // Special handling of jquery-ui buttons: http://stackoverflow.com/questions/3646408/how-can-i-disable-a-button-on-a-jquery-ui-dialog
    $(this).filter("button").button({disabled: false});
};


function AjaxCallbackWaiter(ajaxUrl, button, notificationArea, loadingMessage, errorMessage, inSuccessHandler, inFailureHandler) {
    // Every request that takes less than this, will be intentionally delayed to prevent a flickering effect
    // http://ripper234.com/p/sometimes-a-little-sleep-is-ok/
    var minimalRequestTime = 800;
    var loadingIconUrl = 'http://loadinfo.net/images/preview/11_cyrcle_one_24.gif?1200916238';

    var loadingImageContent = $("<img class='loading-image small' src='" + loadingIconUrl + "'/><span class='loading-text'>" + loadingMessage + "</span>");
    var errorContentTemplate = $("<span class='error ajax-errors'></span>");

    var requestSentTime = null;

    button.click(clickHandler);

    function displayLoadingMessage() {
        clearNotificationArea();
        notificationArea.html(loadingImageContent);
    }

    function clearNotificationArea() {
        notificationArea.html("");
    }

    function displayError(message) {
        var errorContent = errorContentTemplate.clone(errorContentTemplate).html(message);
        notificationArea.html(errorContent);
    }

    function ajaxHandler(result) {
        var requestReceivedTime = new Date().getTime();
        var timeElapsed = requestReceivedTime - requestSentTime;
        // Reset requestSentTime, preparing it for the next request
        requestSentTime = null;

        var sleepTime = Math.max(0, minimalRequestTime - timeElapsed);

        function action() {
            clearNotificationArea();
            button.enable();
            if (result) {
                inSuccessHandler();
            } else {
                displayError(errorMessage);
                inFailureHandler();
            }
        }

        if (sleepTime <= 0) {
            action();
        } else {
            setTimeout(action, sleepTime);
        }
    }

    function failureHandler() {

    }

    function clickHandler(){
        if (requestSentTime !== null) {
            logError("Bad state, expected null");
        }
        requestSentTime = new Date().getTime();
        displayLoadingMessage();
        button.disable();
        $.get(ajaxUrl, 'json').then(ajaxHandler, failureHandler);
    }
}

// Usage:
var ajaxUrl = 'FILL IN YOUR OWN URL HERE';
var button = $("#clickme");
var notificationArea = $(".ajax-notification-area");

var waitingMessage = "Doing Stuff";
var errorMessage = "Not Good<br/> Please try again";

$(document).ready(function(){
  new AjaxCallbackWaiter(
    ajaxUrl,
    button, 
    notificationArea,
    waitingMessage,
    errorMessage,
    function(){
      alert("All is well with the world");
    },
    function(){
      alert("Not good - winter is coming");
    });
});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top