ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

javascript for循环中的异步进程

2019-09-11 00:41:32  阅读:215  来源: 互联网

标签:javascript for-loop asynchronous synchronization


参见英文答案 > JavaScript closure inside loops – simple practical example                                    43个
我正在运行以下形式的事件循环:

var i;
var j = 10;
for (i = 0; i < j; i++) {

    asynchronousProcess(callbackFunction() {
        alert(i);
    });
}

我试图显示一系列显示数字0到10的警报.问题是,当回调函数被触发时,循环已经经历了几次迭代并且它显示了更高的i值.有关如何解决此问题的任何建议?

解决方法:

当所有异步操作都启动时,for循环立即运行完成.当他们将来完成一些时间并调用他们的回调时,循环索引变量i的值将是所有回调的最后一个值.

这是因为for循环不会等待异步操作完成,然后继续循环的下一次迭代,并且因为异步回调在将来的某个时间被调用.因此,循环完成其迭代,然后在异步操作完成时调用回调.因此,循环索引是“完成”并且位于所有回调的最终值.

要解决此问题,您必须为每个回调单独保存循环索引.在Javascript中,这样做的方法是在函数闭包中捕获它.这可以通过专门为此目的创建内联函数闭包来完成(第一个示例如下所示),或者您可以创建一个将索引传递给的外部函数,并让它为您唯一地维护索引(下面显示的第二个示例).

截至2016年,如果你有一个完全符合规范的J6 ES6实现,你也可以使用let定义for循环变量,它将为for循环的每次迭代唯一定义(下面的第三个实现).但请注意,这是ES6实现中的后期实现功能,因此您必须确保执行环境支持该选项.

使用.forEach()进行迭代,因为它创建了自己的函数闭包

someArray.forEach(function(item, i) {
    asynchronousProcess(function(item) {
        console.log(i);
    });
});

使用IIFE创建自己的功能关闭

var j = 10;
for (var i = 0; i < j; i++) {
    (function(cntr) {
        // here the value of i was passed into as the argument cntr
        // and will be captured in this function closure so each
        // iteration of the loop can have it's own value
        asynchronousProcess(function() {
            console.log(cntr);
        });
    })(i);
}

创建或修改外部函数并将其传递给变量

如果你可以修改asynchronousProcess()函数,那么你可以只传递那里的值并让asynchronousProcess()函数将cntr返回给回调,如下所示:

var j = 10;
for (var i = 0; i < j; i++) {
    asynchronousProcess(i, function(cntr) {
        console.log(cntr);
    });
}

使用ES6 let

如果您有一个完全支持ES6的Javascript执行环境,您可以在for循环中使用let,如下所示:

const j = 10;
for (let i = 0; i < j; i++) {
    asynchronousProcess(function() {
        console.log(i);
    });
}

在这样的for循环声明中声明,这将为循环的每次调用创建一个唯一的i值(这是你想要的).

使用promises和async / await进行序列化

如果您的异步函数返回一个promise,并且您希望将异步操作序列化为一个接一个而不是并行运行,并且您在支持async和await的现代环境中运行,那么您有更多选项.

async function someFunction() {
    const j = 10;
    for (let i = 0; i < j; i++) {
        // wait for the promise to resolve before advancing the for loop
        await asynchronousProcess();
        console.log(i);
    }
}

这将确保一次只有一次对asynchronousProcess()的调用,并且for循环在每次调用完成之前都不会前进.这与以前的并行运行异步操作的方案不同,因此它完全取决于您想要的设计.注意:await适用于promise,因此您的函数必须返回异步操作完成时解析/拒绝的promise.另请注意,为了使用await,必须将包含函数声明为async.

标签:javascript,for-loop,asynchronous,synchronization
来源: https://codeday.me/bug/20190910/1802506.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有