javascript --- > 非交互、交互、协作、任务

非交互:

var res = {};

function foo(results) {
    res.foo = results;
}

function bar(results) {
    res.bar = results;
}

ajax( "http://some.url.1", foo);
ajax( "http://some.url.2", bar);

// foo和bar彼此不相关,谁先执行都无所谓..不影响执行结果

交互:

// 交互1:执行顺序影响参数位置

var res = [];

function response(data) {
    res.push(data);
}

ajax( "http://some.url.1", response);
ajax( "http://some.url.2", response);

// ajax请求的结果会放到res中,根据先后顺序有可能产生我们不需要的结果.,
// 如我们想把第一个ajax的结果放到res[0]中,第二个ajax的结果放到res[1]中.但异步的不确定性,有可能先执行第2个ajax.
// 可以对response作如下的改变:

var res = [];

function response(data) {
    if(data.url === "ajax1") {
        res[0] = data;
    }
    else {
        if(data.url === "ajax2") {
            res[1] =data;
        }
    }
}

ajax("http://some.url.1",response);
ajax("http://some.url.2",response);

// 注:data.url是假设从服务器返回的标识字段.
// 交互2:参数缺失
var a, b;

function foo(x) {
    a = x * 2;
    baz();
}

function bar(y) {
    b = y * 2;
    baz();
}

function baz() {
    console.log( a + b);
}

ajax("http://some.url.1", foo);
ajax("http://some.url.2", bar);

// 在两个ajax全部完成前(或只有1个ajax请求完成时,比如ajax1完成)会出现参数丢失的现象:即ajax1完成了,执行foo()方法.
// 先得到a,然后调用baz()方法,此时是没有b(undefined)的.
// 改进baz如下:

function baz() {
    if( a && b ) {
        console.log(a + b);
    }
}
// 交互3:门闩:只执行第一个完成的函数
var a;

function foo(x) {
    a = x * 2;
    baz();
}

function bar(x) {
    a = x / 2;
    baz();
}

function baz() {
    console.log(a);
}

ajax( "http://some.url.1", foo );
ajax( "http://some.url.2", bar );

// 后面执行的会覆盖前面的a
// 我们想a在第一次执行时就确定,改进如下:
function foo(x) {
    if(!a) {
        a = x * 2;
        baz();
    }
}

function bar(x) {
    if(!a) {
        a = x / 2;
        baz();
    }
}

协作:

var res = [];

function response(data) {
    res = res.concat( data.map( function(val) {
            return val * 2;
        })
    );
}

ajax( "http://some.url.1", response);
ajax( "http://some.url.2", response);

// 上述会将ajax请求的数据,全部翻倍..表面上看去没有问题...考虑1000万条记录
// 你会发现,一个回调函数会占用很长的时间,导致期间用户什么都不能做.what a pain..
// 改进如下:
function reponse(data) {
    var chunk = data.splice(0, 1000);
     
    res = res.concat( chunk.map( function (val) { 
            return val * 2;
        })     
    );
     
    if (data.length > 0) {
        setTimeout( function () {
            response(data);
        }, 0 );
    }
}

// 将大数据量切成小块.然后使用setTimeout放入到事件循环队列.这样就可以在处理数据的时候,同时让其他等待的事件有机会运行.
// 事件循环队列的伪代码如下:

var eventLoop = [];  
var event;

while(true) {   // 永远执行
    // 一次tick
    if( eventLoop.length > 0) {
        event = event.Loop.shift();
         
        try {
            event();
        }
        catch (err) {
            reportError(err);
        }
    }
}

// setTimeout({},0)相当于把response(data)推进了eventLoop.而事件循环是一个一个执行的.

任务:

// ES6一个建立在事件循环队列之上的新概念,任务队列.
console.log("A");

setTimeout( function () {
    console.log( "B" );
}, 0 );

// 理论上的"任务API"
schedule( function(){
    console.log( "C" );
     
    schedule( function() {
        console.log( "D" );
    });
});
// 任务队列是事件循环每一个tick之前执行的.

参考《你不知道的JavaScript》(中卷)P150~P156

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值