关于解决JS遍历多个异步回调完美引用外部变量的几个办法

最近项目里用到了多选图片二维码识别上传,由于二维码识别是异步回调,再次列举一下如何在循环回调引用变量

描述

由于JS里for循环是同步任务,而reader.onloadend是异步任务,所以同步的会先执行完循环结束,等到异步回调引用外部变量所以,始终是循环最后一次值,so,归纳了下面三种方式

Promise

Promise.all函数可以并行调用参数中的Promise对象方法,并且将所有Promise对象方法返回值作为数组输入到then回调中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fileReaderPromise = (file) =>{
let promise = new Promise((resolve, reject) =>{
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = (e) => {
let new_result = e.target.result
resolve(new_result)
}
});
return promise;
}
handle_images = (files) => {
let filesPromise = files.map(file => this.fileReaderPromise(file))
Promise.all(filesPromise)
.then(data => {
data.map((image,index) => console.log('image',image,'index',index))
})
}

自执行函数

创建自执行函数局部作用域,保证外部变量不受影响

1
2
3
4
5
6
7
8
9
10
11
12
13
handle_images = (files) => {
_.map(files, (file,index) => {
(function(new_file,new_index){
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = (e) => {
let new_result = e.target.result
//...这里你可以引用new_file,new_index
console.log('new_file',new_file,'new_index',new_index)
}
}.bind(this)(file,index)
}
}

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
handle_images = (i) => {
let new_i = i
if (new_i<files.length){
let file = files[i]
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = (e) => {
let new_result = e.target.result
//...
console.log('file',file,'i',i)
//逻辑处理完后
new_i++;
this.handle_images(new_i)
}
}
}
//调用
this.handle_images(0)
坚持原创技术分享,您的支持将鼓励我继续创作!