js异步编程

声明:本文绝大部分内容来自《javascriptx学习指南》

异步的使用的场景:

网络请求,如ajax请求
文件系统操作:读写文件等
刻意的时间延迟功能(比如警告)

js对异步编程的支持的三个不同阶段:

callback:回调
promise:承诺
grenerator:生成器阶段

书上的类比:来理解回调和承诺

在一个人满为患且没有预定机制的餐厅找一个空位子。
此时不需要排队等位,当有位子的时候餐厅会打电话给客户。
这就类似回调:给餐厅工作人员提供一些客户信息,允许他们在有位子的时候通知客户。
这样一来,餐厅可以忙自己的事情,而客户也可以做别的事情;没有人在等其他人吃好。
另一家餐厅也许会给客户一个传呼机,在位子准备好后它就会响。
这更像是一个承诺:餐厅工作人员给客户一个承诺,承诺在有空桌子的时候通知客户。
回调

简单的来说,回调就是一个函数,然后在未来的某个时刻调用它。这个函数本身并没有特别之处:它只是一个一般的javascript的函数。通常,会把这些回调函数提供别的函数,或者将他们设为对象属性(又或者在数组中使用他们,这种较少)。一般来说,回调都是匿名函数。
下面一个简单的例子:
使用setTimeout,这是js的内建函数。
setTimetou(f,time)

document.write(`before timeout:`+new Date()+"<br>");
    setTimeout(function(){
        document.write(`after timeout:`+new Date+"<br>");
    },10*1000);//js内建函数,将指函数的执行推迟指定的毫秒数。这里是1分钟。

    document.write(`I happen after set setTimeout!<br>`);
    document.write("Me too!");

结果是刚开始页面只显示:

before timeout:Mon Feb 26 2018 09:09:17 GMT+0800 (中国标准时间)
I happen after set setTimeout!
Me too!

等10s:页面只显示

after timeout:Mon Feb 26 2018 09:09:27 GMT+0800 (中国标准时间)

在一般情况下,除非因为编译问题从而不得不给函数命名,通常都会用匿名函数:

setInterval和clearInterval

setInterval是每隔特定时间运行回调函数,并且一直运行下去。

const start = new Date();
    let i = 0;
    const intervalId = setInterval(function(){
        let now = new Date();
        document.write(intervalId+"<br>");
        if(now.getMinutes() !== start.getMinutes() || ++i>10)
            clearInterval(intervalId);

    },5*1000)

setInterval返回一个ID,在后面可以用来取消(停止)这个调用的。

scope和异步执行

异步执行:scope和闭包如何影响异步执行?
每当一个函数被调用时,都创建了一个闭包:所有函数内部创建的变量(包括形参)只在有被访问的时候才存在。

<script>
function countdown(){
    let i;//成为这个域的变量。所以for循环中的i都是指向一个。
    //所以才导致闭包无法保护for里的变量。而下面的let i是在for里面的,他们是同级的。
    //所以闭包能保护。暂且这样理解。待深入
    console.log("countdown");
    for(i=5;i>=0;i--)
    {
        setTimeout(function(){
            document.write(i===0?"GO":i);
            document.write("<br>");
        },(5-i)*1000);
    }

}
countdown();
</script>

这里的输出结果是6个-1

-1
-1
-1
-1
-1
-1

原因:i定义在for循环的外面。for循环执行完毕时,i的值已经为-1,之后callback函数才开始执行。
理解scope和异步执行时如何关联的:当调用 c() 时,创建了一个包含 i 的闭包。所有在for循环中创建的(包括匿名)回调函数都可以访问i,并且是同一个i

function c(){

    console.log("countdown:");
    for(let i=5;i>=0;i--)//重点:声明在for中
    {

        setTimeout(function(){
            console.log(i===0?"GO":i);
        },1000);
    };
};
c();
循环的过程时先生成6个setTimeout()

分别是:

i=5,setTimeout(f,0);
i=4,setTimeout(f,1000);
i=3,setTimetout(f,2000);
i=2,setTimeout(f,3000);
i=1,setTimeout(f,4000);
i=0,setTimeout(f,5000);

可以看做是这6个不同的操作都已经放到了相应的时间点上了,就等相应的时间点来临,它就做相应的事。

上面的let i在for循环内外差异的理解的参考:

http://blog.csdn.net/baidu_36831253/article/details/79378819
http://blog.csdn.net/qq_33276399/article/details/73131046


错误优先回调

由于回调使异常处理变的很棘手,所以需要一种更好的方式将错误传到回调。于是就出现了在回调中使用第一个参数来接受错误对象的约定。如果该对象为null或undefined,就表示没有错误。

明天继续。去去看看ajax。异步已经有了一个基本概念。等下ajax还是有不理解,再回来补充。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值