各位 JS 高手你好,问一个关于 for 循环使用$.post 替换全局变量的问题,好像是竞争锁之类的

2024-03-18 10:40:31 +08:00
 abccccabc
各位 JS 高手你好,问一个关于 for 循环使用$.post 替换全局变量的问题,好像是竞争锁之类的。
```
var allimg = 获取到的图片数组;
var oldcontent = 原内容;
for(var i=0; i<allimg.length; i++){
$.post('url', 参数, function(ret) {
if(ret['code'] == 200) {
oldcontent = oldcontent.replace(ret['oldimgurl'], ret['newimgurl']);
}else{
console.log(错误信息);
}
}, 'json');
}
```
这样有一个很大的问题:多个异步去修改同一全局变量,必须要锁定全局变量 oldcontent ,不然只有最后 i 循环 修改 oldcontent 生效。
请高手支招?
7246 次点击
所在节点    JavaScript
83 条回复
abccccabc
2024-03-24 15:12:55 +08:00
@ming159 大哥,你能解释一下,为啥要把$.post 单独提取出来吗?
ming159
2024-03-26 09:21:53 +08:00
确实是异步导致的问题。 但还有其他问题。
1. post 函数是个异步函数
2. for 循环是同步。
3. JS 变量作用域+JS 函数传值都是值传递、
另外补充一点,**JS 只在一个线程上运行**,异步函数是被放到了任务队列中,等待主线程调用的。

所以,原先在 for 循环内部的时候。 执行顺序是 先执行完 for 循环。 然后执行 post 函数( post 函数)。所以当 post 函数执行的时候。url 每次都是数组的最后一个值。 你的情况类似如下
```
console.log("1"); // 主线程
setTimeout(function(){
console.log("2");
},0); // 加入到了 任务队列。
console.log("3");// 主线程
// 又或者
for(var i=0;i<5;i++){
setTimeout(function(){
console.log("变量 i="+i);
},0);
}
```
那么 为什么提取成函数 for 循环内调用就行了。
在 ES6 之前的,JS 是没有块级作用域变量的,也就是 后来为啥引入 let 的原因。 也就是说,在原来 for 循环内部的时候,post 执行时访问的都是同一个变量 i 。但是提成函数时,变量 i 的值被当做函数参数传入函数内。 那么每次 post 的时候,是从函数参数中获取到的。就不是原先 for 循环中定义的 i 了。

所以 前面的兄弟提到,可以用 let 代替 var 也能解决你的问题。是因为 let 定义的是块级作用域。 比如你可以测试一下如下程序
```
// var 定义 i
for(**var** i=0;i<5;i++){
setTimeout(function(){
console.log(i);
},0);
}
// let 定义
for(**let** i=0;i<5;i++){
setTimeout(function(){
console.log(i);
},0);
}
```
abccccabc
2024-03-26 11:31:12 +08:00
@ming159 原来如此,谢谢。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1024619

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX