Javascript 作用域由多个异步回调共享的变量

Javascript 作用域由多个异步回调共享的变量,javascript,jquery,jquery-ui,asynchronous,Javascript,Jquery,Jquery Ui,Asynchronous,在几个异步调用收集数据并填充复杂图形的元素时,我使用和向用户提供反馈 我的问题是:对异步方法需要共享的数据进行范围界定的最佳方式是什么? 这是我正在做的一个简单的例子。我已经使用全局变量使它工作了,但它们有点干扰我,让jsLint抱怨。在documentready函数中传递参数或作用域会破坏它 在我的真实代码中,updateA()等的对应项有数百行,包括XHR调用 JavaScript: HTML: 正在加载 A. 查找 B 正在查找b C 正在查找c 小提琴: 如果您想在那里使用它,我已经

在几个异步调用收集数据并填充复杂图形的元素时,我使用和向用户提供反馈

我的问题是:对异步方法需要共享的数据进行范围界定的最佳方式是什么?

这是我正在做的一个简单的例子。我已经使用全局变量使它工作了,但它们有点干扰我,让jsLint抱怨。在documentready函数中传递参数或作用域会破坏它

在我的真实代码中,
updateA()
等的对应项有数百行,包括XHR调用

JavaScript: HTML: 正在加载


A.

查找

B

正在查找b

C

正在查找c

小提琴:
如果您想在那里使用它,我已经知道了。

您可以将全局变量放入一个“state”对象中,并将其传递给所有回调函数。e、 g

$(function() {
    var progressState = {
        steps: 3,
        ticked: 0,
        otherCounter: 0
    };

    $('#progressbar').progressbar({value: 0});

    async.parallel(
      [
        function(onDoneCallback) {updateA(onDoneCallback, progressState);},
        function(onDoneCallback) {updateB(onDoneCallback, progressState);},
        function(onDoneCallback) {updateC(onDoneCallback, progressState);}
      ],
      function(err, results) { // final callback when they're all done
        tickProgress('All done after ' + progressState.ticked + ' ticks.', true, progressState);
      }
    );
});

然后将updateA、updateB、updateC和tickProgress更改为使用提供的状态对象,而不是全局变量。

一般来说,创建自己的closured
Function-Context'ed
“region”总是一个好主意。可以通过在应用程序周围包装一个自调用匿名函数来实现这一点。这看起来像

(function(window, document, $) {
     // all your app logic goes into here
     var steps = 3;
     var ticked = 0;
     var otherCounter = 0;

     // ...
}(this, this.document, jQuery))
这样,您就永远不会破坏全局名称空间。当然,有时你需要一个全局对象,但你真的应该尽量避免,除非绝对必要。

让我在JS聊天室中开始使用这种方法

它使用了一个全局对象,但我更喜欢对象中方法的逻辑封装,而不是和的建议


谢谢你的回答,@kirilloid,但我不喜欢通过这种方法的过度争论,因为它需要一个全局对象。
$(function() {
    var progressState = {
        steps: 3,
        ticked: 0,
        otherCounter: 0
    };

    $('#progressbar').progressbar({value: 0});

    async.parallel(
      [
        function(onDoneCallback) {updateA(onDoneCallback, progressState);},
        function(onDoneCallback) {updateB(onDoneCallback, progressState);},
        function(onDoneCallback) {updateC(onDoneCallback, progressState);}
      ],
      function(err, results) { // final callback when they're all done
        tickProgress('All done after ' + progressState.ticked + ' ticks.', true, progressState);
      }
    );
});
(function(window, document, $) {
     // all your app logic goes into here
     var steps = 3;
     var ticked = 0;
     var otherCounter = 0;

     // ...
}(this, this.document, jQuery))
var Updater = (function() {
    var steps = 3;
    var ticked = 0;
    var otherCounter = 0;

    function a(onDoneCallback) {
        setTimeout(function() {
            $('#a').html('A is foo. otherCounter ' + otherCounter);
            tickProgress('updated A at otherCounter ' + otherCounter);
            otherCounter++;
            onDoneCallback(null, 'A done');
        }, 1000);

    }

    function b(onDoneCallback) {
        setTimeout(function() {
            $('#b').html('B is bottle. otherCounter ' + otherCounter);
            tickProgress('updated B at otherCounter ' + otherCounter);
            otherCounter++;
            onDoneCallback(null, 'B is OK');
        }, 100);
    }

    function c(onDoneCallback) {
        setTimeout(function() {
            $('#c').html('C is cauliflower. otherCounter ' + otherCounter);
            tickProgress('updated C at otherCounter ' + otherCounter);
            otherCounter++;
            onDoneCallback(null, 'C done');
        }, 2000);
    }

    function tickProgress(message) {
        var curvalue = $('#progressbar').progressbar('option', 'value');
        var done = false;

        if (arguments.length > 1) {
            done = arguments[1];
        }

        $('#progress_text').html(message);

        if (done) {
            $('#progressbar').progressbar('option', 'value', 100);
        }
        else {
            $('#progressbar').progressbar('option', 'value', curvalue + 100 / Updater.getSteps());
        }
        Updater.tick(); // global OK here?
    }

    return {
        a: a,
        b: b,
        c: c,
        tickProgress: tickProgress,
        tick: function() {
            ticked++;
        },
        getTicks: function() {
            return ticked;
        },
        getSteps: function() {
            return steps;
        }
    };
}());

$(function() {
    $('#progressbar').progressbar({
        value: 0
    });

    async.parallel([
        function(onDoneCallback) {
        Updater.a(onDoneCallback);},
        function(onDoneCallback) {
        Updater.b(onDoneCallback);},
        function(onDoneCallback) {
        Updater.c(onDoneCallback);}
    ], function(err, results) { // final callback when they're all done
        Updater.tickProgress('All done after ' + Updater.getTicks() + ' ticks.', true);
    });
});