美文网首页
for循环里的异步操作如何处理

for循环里的异步操作如何处理

作者: Amy_yqh | 来源:发表于2020-02-29 23:20 被阅读0次

    首先来看一个比较简单的问题,我们想实现的就是每隔1s输出0-4的值,就是这么简单,看下错误写法:

    function test() {
        for (var i = 0; i < 5; ++i) {
            setTimeout(function() {
                console.log("index is :", i);
            }, 1000);
        }
    }
    test();
    

    以上代码会如何输出?输出如下

    index is : 5
    index is : 5
    index is : 5
    index is : 5
    index is : 5
    

    而且该操作几乎是在同一时间完成,setTimeout定时根本就没有起作用,这是因为:单线程的js在操作时,对于这种异步操作,会先进行一次“保存”,即把异步操作放到堆栈中,等前面的程序执行完,堆栈中的异步操作就会执行。等到整个for循环执行结束后,此时i的值已经变成5,因为setTimeout是写在for循环中的,相当于存在5次定时调用,这5次调用均是在for循环结束后进行的,所以自然而然输出都是5,正确的实现有几种,一般情况下,如下:

    递归

    box6();
     
    function box7(param) {
        if (param < 5) {
            console.log("index is :", param);
            setTimeout(function() {
                box7(param + 1);
            }, 1000)
        }
    }
    box7(0);
    

    正确实现每隔1s打印输出如下:

    index is : 0
    index is : 1
    index is : 2
    index is : 3
    index is : 4
    

    使用递归实现的倒计时:

    function showTime(count) {
        console.log("count is : ", count);
        if (count == 0) {
            console.log("All is Done!");
        } else {
            count -= 1;
            setTimeout(function() {
                showTime(count);
            }, 1000);
        }
    }
     
    showTime(20);
    

    自执行函数

    function test() {
        for (var i = 0; i < 5; ++i) {
            (function(i){
            setTimeout(function() {
                console.log("index is :", i);
            }, 1000)
            })(i)
        }
    }
    test();
    

    异步操作使用异步函数包裹起来,i每次执行都不把i作为参赛传到函数中

    let 声明i

    function test() {
        for (let i = 0; i < 5; ++i) {
            setTimeout(function() {
                console.log("index is :", i);
            }, 1000)
        }
    }
    test();
    

    使用let定义i变量,let 的的作用域是块级作用域

    async、await实现

    var asyncFunc = function(arr, i) {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                arr.push(i);
                console.log("index is : ", i);
                resolve();
            }, 1000);
        });
    }
     
    var box5 = async function() {
        var arr = [];
        for (var i = 0; i < 5; i++) {
            await asyncFunc(arr, i);
        }
        console.log(arr);
    }
     
    box5();
    

    同样实现每隔1s正确地打印输出如下:

    index is :  0
    index is :  1
    index is :  2
    index is :  3
    index is :  4
    [ 0, 1, 2, 3, 4 ]
    

    使用promise,函数会等待他执行完才会继续执行下一行代码,相当于是同步代码

    相关文章

      网友评论

          本文标题:for循环里的异步操作如何处理

          本文链接:https://www.haomeiwen.com/subject/ocaxchtx.html