在循环中定义ajax回调覆盖

时间:2014-03-05 09:23:57

标签: javascript jquery ajax coffeescript

我做了一个ajax预过滤器,等待一个模态窗口在进行原始回调之前消失,并且效果很好......

$.ajaxPrefilter ( options, originalOptions, jqXHR )->

    # perhaps these could be defined in a loop from an array
    jqXHROriginaldone = jqXHR.done
    jqXHROriginalfail = jqXHR.fail

    jqXHR.done = ->
        args = arguments
        myfunc = ->
            $(listener).off "ajax.progress.dismissed", myfunc
            jqXHROriginaldone args
        $(listener).on "ajax.progress.dismissed", myfunc

    jqXHR.fail = ->
        args = arguments
        myfunc = ->
            $(listener).off "ajax.progress.dismissed", myfunc
            jqXHROriginalfail args
        $(listener).on "ajax.progress.dismissed", myfunc

我不喜欢为每种状态类型重复我的代码...我想改变以便我可以在循环中设置所有状态(完成/失败/等...)...

$.ajaxPrefilter ( options, originalOptions, jqXHR )->

    # object to store original callbacks for later use
    originals = {}

    for status in ['done','fail']

        originals[status] = jqXHR[status]
        jqXHR[status] = ->
            args = arguments
            myfunc = ->
                $(listener).off "ajax.progress.dismissed", myfunc
                originals[status] args
            $(listener).on "ajax.progress.dismissed", myfunc

它看起来像我的等效代码,但它失败了,并且在控制台中没有显示错误,只是没有运行回调函数。

为什么我的循环方法有效?

1 个答案:

答案 0 :(得分:1)

在循环内构建函数会引发一个红色标记。在实际使用之前,不会评估您的status变量。如果我们查看您的myfunc

myfunc = ->
    $(listener).off "ajax.progress.dismissed", myfunc
    originals[status] args

我们会看到status引用,在调用myfunc之前不会对其进行评估。发生这种情况时,status始终为'fail',因为这是循环结束时status的内容。

JavaScript中的常用解决方案是使用SIF作为循环体:

for(i = 0; i < n; ++i)
    (function(i) {
        //...
    })(i);

但在CoffeeScript中有do

  

当使用JavaScript循环生成函数时,通常会插入一个闭包装,以确保循环变量被关闭,并且所有生成的函数不只是共享最终值。 CoffeeScript提供do关键字,它立即调用传递的函数,转发任何参数。

所以这样的事情会更好:

for status in ['done','fail']
    do (status) ->
        # What you have now...