Простая клиентская структура / шаблон для упрощения выполнения асинхронных вызовов? - PullRequest
2 голосов
/ 21 февраля 2012

В настоящее время мы не используем никаких серьезных клиентских сред, кроме jQuery (и jQuery.ui + validation + плагины мастера форм).

Проблема, которая несколько раз всплывает в нашем коде, такова:

  1. У нас есть кнопка, которая инициирует Ajax-вызов на сервер.
  2. Во время вызова мы отображаем значок «загрузки» с некоторым текстом
  3. Еслисервер возвращает результат слишком быстро (например, <200 мс), мы «спим» на 200 миллис (используя <code>setTimeout()), , чтобы предотвратить мерцание значка ожидания и текста .
  4. После max(the call returns, a minimal timeout) мы очищаем значок загрузки и текст.
  5. Затем мы либо отображаем текст ошибки, если была какая-то проблема в вызове ajax (сервер не возвращает 500, а пользовательский json, которыйимеет свойство «сообщение об ошибке». На самом деле, иногда у нас есть такое свойство в ответе для каждого поля формы ... и затем мы сопоставляем ошибки с полями формы ... но я отступаю).
  6. В случаеуспеха мы делаем ... что-то (зависит от ситуации).

Я пытаюсь свести к минимуму повторное использование кода и либо написать, либо повторно использовать шаблон / фрагмент кода / фреймворк, который делает это.Хотя я, вероятно, не начну использовать полностью новую сверхпрочную инфраструктуру только для этого варианта использования, я все же хотел бы знать, какие у меня есть варианты ... возможно, такая инфраструктура на стороне клиента подойдет и для других вещей.Если есть облегченная структура, которая не требует, чтобы я переворачивал весь код с ног на голову, и я мог бы использовать ее только в определенных случаях, мы могли бы использовать ее вместо того, чтобы заново изобретать колесо.

Я только недавно слышало Ember.js - это хорошо подходит для решения этой проблемы?Как бы вы решили это?

Ответы [ 3 ]

4 голосов
/ 21 февраля 2012
$(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);
});
0 голосов
/ 22 февраля 2012

Просто оберните $ .ajax в вашу собственную функцию. таким образом, вы можете реализовать свою собственную очередь и т.д. Я бы предложил сделать для этого компонент jquery. Он может стать довольно мощным, например, вы также можете передавать заголовки http и т. Д.
Что касается рамок, это зависит от ваших требований.
Например, вы можете рассмотреть Kendo UI, он имеет хорошую основу для создания источников данных: http://demos.kendoui.com/web/datasource/index.html.

0 голосов
/ 22 февраля 2012

Рабочий пример кода (ну, почти)

В любом случае я собирался что-то повторить в ответе @ DefyGravity - его идея хороша, но все еще является псевдокодом / не полностью завершена. Вот мой рабочий код ( почти рабочая демонстрация , вплоть до самого URL Ajax и настроек пользовательского интерфейса)

Код и пример использования:

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

    // Special handling of jquery-ui buttons: /3124696/kak-ya-mogu-otklychit-knopku-v-dialogovom-okne-jquery-ui
    $(this).filter("button").button({disabled: true});
};
jQuery.fn.enable = function() {
    $(this).removeAttr("disabled");
    $(this).addClass("enabled");
    // Special handling of jquery-ui buttons: /3124696/kak-ya-mogu-otklychit-knopku-v-dialogovom-okne-jquery-ui
    $(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");
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...