确定由多个异步回调共享的变量

Nat*_*han 4 javascript jquery asynchronous jquery-ui

我正在使用Caolan McMahonasync.js库jQueryUI进度条向用户提供反馈,同时几个异步调用收集数据并填充复杂图形的元素.

我的问题是:对于需要由异步方法共享的数据进行范围调整的最佳方法什么?

这是我正在做的简化示例.我已经使用全局变量工作,但他们打扰了我一点,让jsLint抱怨.在文档就绪功能中传递参数或作用域会破坏它.

updateA()et 的对应物.人.在我的真实代码中有数百行并包含XHR调用.

JavaScript的:

// global variables.  Bad?
var steps = 3;
var ticked = 0;
var otherCounter = 0;

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

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

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 / steps);
    }

    ticked++; // global OK here?
}

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

}

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

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

HTML:

<p id="progress_text" style="background:yellow">Loading...</p>
<div id="progressbar"></div>
<hr />
<h2>a</h2>
<p id="a">Looking up a...</p>

<h2>b</h2>
<p id="b">Looking up b...</p>

<h2>c</h2>
<p id="c">Looking up c...</p>
Run Code Online (Sandbox Code Playgroud)

小提琴:

我有JSFiddle的示例代码,如果你想在那里敲打它.

jAn*_*ndy 5

通常,创建一个自己封闭的 Function-Context'ed "区域" 总是一个好主意.您可以通过在应用程序周围包装一个自调用匿名函数来实现.这看起来像

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

     // ...
}(this, this.document, jQuery))
Run Code Online (Sandbox Code Playgroud)

这样,你永远不会破坏全局命名空间.当然,你有时需要有一个全局对象,但除非绝对必要,否则你应该尽量避免这种情况.