代码之家  ›  专栏  ›  技术社区  ›  David Citron

在javascript中将状态传递给回调是否适当地使用闭包?

  •  2
  • David Citron  · 技术社区  · 16 年前

    假设您想在javascript中发出一个异步请求,但是您想向回调方法传递一些状态。以下是在javascript中适当使用闭包吗?

    function getSomethingAsync(someState, callback) {
        var req = abc.createRequestObject(someParams);
        req.invoke(makeCallback(someState, callback));
    }
    
    function makeCallback(someState, callback) {
        return function getSomethingCallback(data) {
            var result = processDataUsingState(data, someState);
            callback(result); // alternately/optionally pass someState along to result
        }
    }
    

    如果没有,有更好或更惯用的方法吗?

    4 回复  |  直到 13 年前
        1
  •  2
  •   Jason Bunting    16 年前

    我看不出这方面的任何直接问题——闭包之所以强大,有很多原因,其中之一就是消除了使用全局变量进行状态维护的需要。

    也就是说,对于闭包,唯一需要注意的是通常发生在IE中的内存泄漏,但是这些泄漏通常是IIRC,与DOM元素和附加在其上的事件处理程序相关。

    前进!

        2
  •  1
  •   David Citron    13 年前

    更惯用的方法是 Function.bind ,那么不需要复制代码来创建闭包。我将使用一个简单的示例(没有您的自定义代码)来解释

    /**
     * Retrieves the content of a url asyunchronously
     * The callback will be called with one parameter: the html retrieved
     */
    function getUrl(url, callback) {
        $.ajax({url: url, success: function(data) {
            callback(data);
        }})    
    }
    
    // Now lets' call getUrl twice, specifying the same 
    // callback but a different id will be passed to each
    function updateHtml(id, html) {
        $('#' + id).html(html);
    }
    
    
    // By calling bind on the callback, updateHTML will be called with 
    // the parameters you passed to it, plus the parameters that are used
    // when the callback is actually called (inside )
    // The first parameter is the context (this) to use, since we don't care,
    // I'm passing in window since it's the default context
    getUrl('/get/something.html', updateHTML.bind(window, 'node1'));
    // results in updateHTML('node1', 'response HTML here') being called
    getUrl('/get/something-else.html', updateHTML.bind(window, 'node2'));
    // results in updateHTML('node2', 'response HTML here') being called
    

    函数绑定 是新的,因此如果需要向后支持,请查看 函数绑定

    最后,我知道这个问题没有被标记为jquery。这只是显示异步函数而不处理跨浏览器问题的最快方法。

        3
  •  0
  •   Javier    16 年前

    使用匿名函数更好(更好):

    function getSomethingAsync (someState, callback) {
        req.invoke (function (data) {
           var result = processDataUsingState (data, someState);
           callback (result);
        });
    }
    
        4
  •  0
  •   pete otaqui    13 年前

    还可以在带有call()/apply()的函数中操纵“this”的值。

    例如,指定异步方法的另一个参数是要在回调中用作“this”的对象。这就是jquery在事件回调中将dom节点设置为“this”的方式。

    function getSomethingAsync(callback, scope) {
        var req = abc.createRequestObject(someParams);
        req.invoke(function(rsp) {
          callback.apply(scope, [rsp]);
        });
    }
    
    // usage:
    getSomethingAsync(function() {console.log(this.someState)}, {someState:'value'});