Javascript 简化异步调用的简单客户端框架/模式?

Javascript 简化异步调用的简单客户端框架/模式?,javascript,ajax,frameworks,ember.js,Javascript,Ajax,Frameworks,Ember.js,除了jQuery(和jQuery.ui+验证+表单向导插件),我们目前没有使用任何严肃的客户端框架 代码中多次出现的问题是: 我们有一个按钮,用于启动对服务器的Ajax调用 在通话过程中,我们会显示一个带有文本的“加载”图标 如果服务器返回结果太快(例如

除了jQuery(和jQuery.ui+验证+表单向导插件),我们目前没有使用任何严肃的客户端框架

代码中多次出现的问题是:

  • 我们有一个按钮,用于启动对服务器的Ajax调用
  • 在通话过程中,我们会显示一个带有文本的“加载”图标
  • 如果服务器返回结果太快(例如<200毫秒),我们将“睡眠”200毫秒(使用
    setTimeout()
  • max(调用返回,最小超时)
    之后,我们清除加载图标和文本
  • 然后,如果ajax调用中出现问题,我们要么显示错误文本(服务器不返回500,而是返回一个具有“错误消息”属性的自定义json。事实上,有时我们在每个表单字段的响应中都有这样的属性……然后我们将错误与表单字段匹配……但我离题了)
  • 如果成功,我们会。。。(视情况而定)
  • 我试图最大限度地减少代码重用,并编写或重用实现这一点的模式/代码片段/框架。虽然我可能不会仅仅为这个用例使用一个全新的重载框架,但我仍然想知道我的选项是什么。。。也许这样的客户端框架也适用于其他方面。如果有一个轻量级的框架,不需要我把所有的代码颠倒过来,我可以在特定的情况下使用,那么我们实际上可以使用它,而不是重新发明轮子

    我最近刚刚听说——它适合解决这个问题吗?您将如何解决它?

    $(函数(){
    
    $(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);
    });
    
    var buttonSelector=“#button”; $('body')。在({'click':函数(evt)上{ var$按钮=$(此按钮); $button.toggleClass('loading'); 变量时间=新日期(); $.get('some/ajax')。然后(函数(数据、文本、jqXhr){ //负载工作的典型猜测 $button.empty(); $(数据).wrap($按钮); }).fail(函数(数据、文本、jqXhr){ 警报(“失败”); }).done(函数(数据、文本、jqXhr){ var persed=新日期(); 如果((经过的时间)<200){ 警惕(“做空,等待”); } $button.toggleClass('loading'); }); }},按钮选择器,空); });
    $(函数(){
    var buttonSelector=“#button”;
    $('body')。在({'click':函数(evt)上{
    var$按钮=$(此按钮);
    $button.toggleClass('loading');
    变量时间=新日期();
    $.get('some/ajax')。然后(函数(数据、文本、jqXhr){
    //负载工作的典型猜测
    $button.empty();
    $(数据).wrap($按钮);
    }).fail(函数(数据、文本、jqXhr){
    警报(“失败”);
    }).done(函数(数据、文本、jqXhr){
    var persed=新日期();
    如果((经过的时间)<200){
    警惕(“做空,等待”);
    }
    $button.toggleClass('loading');
    });
    }},按钮选择器,空);
    });
    
    工作示例代码(好的,差不多)

    不管怎样,我一直在寻找@DefyGravity的答案——他的想法很好,但仍然是伪代码/还没有完全完成。这是我的工作代码(,直到Ajax URL本身,以及UI调整)

    代码和用法示例:

    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");
        });
    });
    
    jQuery.fn.disable=function(){
    $(此).attr(“已禁用”、“已禁用”);
    $(此).removeClass(“已启用”);
    //jquery ui按钮的特殊处理: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=函数(){
    $(此).removeAttr(“禁用”);
    $(此).addClass(“已启用”);
    //jquery ui按钮的特殊处理:http://stackoverflow.com/questions/3646408/how-can-i-disable-a-button-on-a-jquery-ui-dialog
    $(this.filter(“button”).button({disabled:false});
    };
    函数AjaxCallBackaiter(ajaxUrl、按钮、通知区域、加载消息、错误消息、失败处理程序、导入处理程序){
    //每一个少于这个的请求都会被故意延迟,以防止出现闪烁效果
    // http://ripper234.com/p/sometimes-a-little-sleep-is-ok/
    var最小请求时间=800;
    var loadingIconUrl=http://loadinfo.net/images/preview/11_cyrcle_one_24.gif?1200916238';
    var loadingImageContent=$(“”+loadingMessage+“”);
    var errorContentTemplate=$(“”);
    var requestSentTime=null;
    按钮。单击(clickHandler);
    函数displayLoadingMessage(){
    clearNotificationArea();
    html(加载图像内容);
    }
    函数clearNotificationArea(){
    notificationArea.html(“”);
    }
    函数显示错误(消息){
    var errorContent=errorContentTemplate.clone(errorContentTemplate.html(message);
    notificationArea.html(errorContent);
    }
    函数ajaxHandler(结果){
    var requestReceivedTime=new Date().getTime();
    var timeappeased=requestReceivedTime-requestSentTime;
    //重置requestSentTime,为下一个请求做好准备
    requestSentTime=null;
    var sleepTime=Math.max(0,minimalRequestTime-timepassed);
    函数动作(){
    clearNotificationArea();
    按钮。启用();
    如果(结果){
    不成功处理程序();
    }否则{
    显示错误(errorMessage);
    inFailureHandler();
    }
    }
    
    if(睡眠时间工作示例代码(很好,几乎)

    不管怎样,我还是想按照@DefyGravity的回答做点什么——他的想法很好,但仍然是伪代码/还没有完全完成

    代码和用法示例:

    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");
        });
    });
    
    jQuery.fn.disable=function(){
    $(此).attr(“已禁用”、“已禁用”);
    $(此).removeClass(“已启用”);
    //jquery ui按钮的特殊处理:http://stackoverflow.com/questions/3646408/how-can-i-disable-a-button-on-a-jq