إطار/نمط بسيط من جانب العميل لتبسيط إجراء المكالمات غير المتزامنة؟

StackOverflow https://stackoverflow.com/questions/9383091

سؤال

نحن لا نستخدم حاليًا أي إطار عمل جاد من جانب العميل إلى جانب jQuery (و jQuery.ui + التحقق من الصحة + المكونات الإضافية لمعالج النماذج).

المشكلة التي تظهر عدة مرات في الكود الخاص بنا هي:

  1. لدينا زر يبدأ اتصال Ajax بالخادم.
  2. أثناء إجراء المكالمة، نعرض رمز "تحميل" مع بعض النص
  3. إذا قام الخادم بإرجاع النتيجة بسرعة كبيرة (على سبيل المثال.<200 مللي ثانية)، نحن "ننام" لمدة 200 ملي (باستخدام setTimeout()), لمنع وميض أيقونة الانتظار والنص.
  4. بعد max(the call returns, a minimal timeout), ، نقوم بمسح أيقونة التحميل والنص.
  5. نقوم بعد ذلك إما بعرض نص خطأ، إذا كانت هناك مشكلة ما في استدعاء ajax (لا يقوم الخادم بإرجاع 500، ولكن json مخصص يحتوي على خاصية "رسالة خطأ".في الواقع، في بعض الأحيان لدينا مثل هذه الخاصية في الرد لكل حقل نموذج ...ثم نقوم بمطابقة الأخطاء مع حقول النموذج ...ولكني استطرادا).
  6. وفي حالة النجاح نقوم...شيء (يعتمد على الوضع).

أحاول تقليل إعادة استخدام التعليمات البرمجية، وإما كتابة أو إعادة استخدام نمط/جزء من التعليمات البرمجية/إطار العمل الذي يفعل ذلك.على الرغم من أنني ربما لن أبدأ في استخدام إطار عمل جديد كامل للخدمة الشاقة لحالة الاستخدام هذه فقط، إلا أنني ما زلت أرغب في معرفة الخيارات المتاحة أمامي...ربما يكون مثل هذا الإطار من جانب العميل مفيدًا لأشياء أخرى أيضًا.إذا كان هناك إطار عمل خفيف الوزن لا يتطلب مني قلب كل التعليمات البرمجية الخاصة بي رأسًا على عقب، ويمكنني استخدامه فقط في حالات محددة، فقد نستخدمه بالفعل بدلاً من إعادة اختراع العجلة.

لقد سمعت للتو عن Ember.js - هل هو مناسب لحل هذه المشكلة؟كيف يمكنك حلها؟

هل كانت مفيدة؟

المحلول

$(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);
});

نصائح أخرى

ما عليك سوى لف $.ajax في وظيفتك الخاصة.بهذه الطريقة يمكنك تنفيذ قائمة الانتظار الخاصة بك وما إلى ذلك.أود أن أقترح إنشاء مكون jquery لهذا الغرض.يمكن أن يصبح قويًا جدًا، على سبيل المثال، يمكنك أيضًا تمرير رؤوس http وما إلى ذلك.
فيما يتعلق بالأطر، فهذا يعتمد على متطلباتك.
على سبيل المثال، قد تفكر في واجهة Kendo UI، فهي تتمتع بإطار عمل جيد لإنشاء مصادر البيانات:http://demos.kendoui.com/web/datasource/index.html.

رمز عينة العمل (حسنا، تقريبا)

كنت أبحث عن شيء ما على غرار إجابة @DefyGravity على أي حال - فكرته جيدة، لكنها لا تزال رمزًا زائفًا/غير مكتملة بالكامل.هنا هو رمز العمل الخاص بي (التجريبي العمل تقريبا, ، حتى عنوان URL الخاص بـ Ajax نفسه، وتعديلات واجهة المستخدم)

الكود ومثال الاستخدام:

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");
    });
});
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top