最近项目里用到了多选图片二维码识别上传,由于二维码识别是异步回调,再次列举一下如何在循环回调引用变量
描述
由于JS里for循环是同步任务,而reader.onloadend是异步任务,所以同步的会先执行完循环结束,等到异步回调引用外部变量所以,始终是循环最后一次值,so,归纳了下面三种方式
Promise
Promise.all函数可以并行调用参数中的Promise对象方法,并且将所有Promise对象方法返回值作为数组输入到then回调中
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))
})
}
自执行函数
创建自执行函数局部作用域,保证外部变量不受影响
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)
}
}
递归
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)