使用jQuery延迟管理同步和异步JavaScript函数

时间:2013-12-04 19:49:20

标签: javascript jquery asynchronous jquery-deferred

我需要通过Socket.IO(客户端)通过websockets运行一系列调用。由于我没有使用$ .ajax,jQuery的延迟函数也不会集成,我将不得不手动处理promises。随着每个websocket调用,我通过回调,我很快就会看到这个项目如何失控。这是我的websocket调用如何工作的简化示例(不包括所有连接处理代码):

function js2node(nodeFunction, data, callback){
    socket.emit('incoming', nodeFunction, data, callback);
}

function sampleServerCall(){
    js2node('sampleCall', 'something', 'sampleCallback');
}

function sampleCallback(json){
    // Handle data
}

sampleServerCall();

我将与服务器进行相当多的讨论,所有调用都将是异步的,但有些需要按特定顺序返回。输入jQuery deferred。这是一些有效的代码:

var deferredArray = [];

$(function(){
    $.when(  // Any order
        getData1(),
        getData2()
    ).then(function(){  // Must have responses from dataCallback1 and dataCallback2 before doing this...
        $.when(  // Any order
            getData3(),
            getData4()
        ).then(function(){  // Must have responses from dataCallback3 and dataCallback4 before doing this...
            getData5();
        });
    });
});

function getData1(){
    js2node('data1', 'something', 'dataCallback1');
    deferredArray[0] = new $.Deferred();
    return deferredArray[0].promise();
}

function getData2(){
    js2node('data2', 'something', 'dataCallback2');
    deferredArray[1] = new $.Deferred();
    return deferredArray[1].promise();
}

function getData3(){
    js2node('data3', 'something', 'dataCallback3');
    deferredArray[2] = new $.Deferred();
    return deferredArray[2].promise();
}

function getData4(){
    js2node('data4', 'something', 'dataCallback4');
    deferredArray[3] = new $.Deferred();
    return deferredArray[3].promise();
}

function getData5(){
    js2node('data5', 'something', 'dataCallback5');
    deferredArray[4] = new $.Deferred();
    return deferredArray[4].promise();
}

function dataCallback1(json){
    // Handle data
    deferredArray[0].resolve();
}

function dataCallback2(json){
    // Handle data
    deferredArray[1].resolve();
}

function dataCallback3(json){
    // Handle data
    deferredArray[2].resolve();
}

function dataCallback4(json){
    // Handle data
    deferredArray[3].resolve();
}

function dataCallback5(json){
    // Handle data
    deferredArray[4].resolve();
}

正如你所看到的那样,当我添加功能时,我仍然坚持使用嵌套式回调,因为我正在使用/然后嵌套可能会更深入。 Deferred对我来说是一个新概念,但我已经读过它应该在这样的情况下提供帮助。我觉得必须有比我现在做的更好的方式。任何人都可以帮我更有效地设置它吗?

2 个答案:

答案 0 :(得分:6)

你可以用.then:

做更多事情
$(function(){
    $.when(
        doSock('data1', 'something'),
        doSock('data2', 'something')
    ).then(function(data1, data2){
        return $.when(
            doSock('data3', 'something'),
            doSock('data4', 'something')
        );
    }).then(function(data3, data4){
        return doSock('data5', 'something');
    });
});

这样你的嵌套永远不会比那更深。

(我使用了adeneo的辅助方法)

答案 1 :(得分:3)

使用更好的辅助函数肯定会有所帮助,但你仍然需要使用$ .when和$ .then构建调用以正确的顺序执行它们

function doSock(nodeFunction, data) {
    var def = new $.Deferred();
    socket.emit('incoming', nodeFunction, data, function(received) {
        def.resolve(received)
    });
    return def.promise();
}

$(function(){
    $.when(
        doSock('data1', 'something'),
        doSock('data2', 'something')
    ).then(function(data1, data2){
        $.when(
            doSock('data3', 'something'),
            doSock('data4', 'something')
        ).then(function(data3, data4){
            doSock('data5', 'something');
        });
    });
});