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

281 天前
 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 生效。
请高手支招?
5874 次点击
所在节点    JavaScript
83 条回复
churchill
281 天前
锁?
wu67
281 天前
经典闭包问题
weixind
281 天前
没看懂你这段代码是要干啥?通过旧数组获取新数组吗?如果是作用域问题的话,用 let 替换 var i=0 中 var 。搜索关键词“块级作用域”。https://juejin.cn/post/6844903951351939080?searchId=202403181050254A1BA64DD54934892197
yunying
281 天前
@wu67 正解
nitmali
281 天前
说说需求是啥
zzxqd
281 天前
没那么复杂,加下标即可
```
var oldcontent = allimg.map(item => {return item.url})
...
if (ret['code'] === 200) {
oldcontent[i].replace(ret['oldimgurl'],ret['newimgurl'])
}

```
codespots
281 天前
闭包的经典应用场景之一
webszy
281 天前
首先,$.post 明显是异步请求,那么肯定会出现最后一个返回的内容,覆盖前面的内容。所以你有 2 种解决办法:1 、Promise.all 获取所以返回结果再修改,2 、使用 async/await 转为同步处理
qrobot
281 天前
楼上都没看懂他的问题我来简单整理回答一下

```
// 这应该是是一个数组
var allimg = []

// 这应该是是一个字符串类型
var oldcontent ="";

// 循环上面的数组进行批量调用请求
for(var i=0; i<allimg.length; i++){
// 这里我猜用的是 jquery 的 post 方法, 是一个异步回调
$.post('url', 参数, function(ret) {
if(ret['code'] == 200) {
oldcontent = oldcontent.replace(ret['oldimgurl'], ret['newimgurl']);
}else{
console.log(错误信息);
}
}, 'json');
}
```

楼主问, 为啥在调用

```
oldcontent = oldcontent.replace(ret['oldimgurl'], ret['newimgurl']);
```

这个方法的时候, 获取的是上一次循环的内容了.


以下请各位 JS 高手帮忙解决以下.
qrobot
281 天前
我发消息的时候 7l 和 8l 还不在, 7l, 8l 是正确答案
abccccabc
281 天前
@nitmali 使用场景是这样的。

oldcontent="我是文章内容,里面有多个远程图片,如<img src='https://www.baidu.com/s/abc.jpg'> <img src='https://www.csdn.com/s/123.jpg'> <img src='https://www.jd.com/s/mn.jpg'>,甚至有些文章内容的图片会更多,现在的需求就是将这些文章内容中的图片进行本地化。替换掉文章内容远程图片,最后入库”。


var allimg = ['https://www.baidu.com/s/abc.jpg', 'https://www.csdn.com/s/123.jpg', 'https://www.jd.com/s/mn.jpg'];


$.post 是异步,如何在循环的异步中替换掉 oldcontent 呢?

@zzxqd var oldcontent = allimg.map(item => {return item.url}) ,这一句什么意思呢?


各位,我 JS 水平不高,就会用一个 jquery 。
abccccabc
281 天前
@webszy 1 、Promise.all 获取所以返回结果再修改,2 、使用 async/await 转为同步处理

我去看看 Promise.all ,同步会卡浏览器,现在就是用的这种方法,图片少了还好,图片一多。这个浏览器什么也干不了。
ZnductR0MjHvjRQ3
281 天前
我不懂你的意思 你每次循环都修改了 oldcontent 那么循环结束一定是最后一次循环赋的值生效啊 这有问题吗?
你代码和你的问的就好像是
a = 1
a = 2
a = 3
a = 6
为什么 a = 6 ??
并且你也没用说清楚你到底是在哪里使用的 oldcontent 如果是在循环结束的话 那么 oldcontent 应该等于 原内容
那么如果你等待了全部的请求结束 那就是上面的问题啊 a 就应该等于 6
qrobot
281 天前
@abccccabc 哥们你直接留个联系方式把, 我远程帮你解决把, 我真的看不下去
ZnductR0MjHvjRQ3
281 天前
@abccccabc 图片多也不一定啊 promise.all 你可以在外层再做一层并发控制就好了 限制最大并发量然后后续等待
abccccabc
281 天前
@qrobot 你说对了。估计你早有解决方案了
limars
281 天前
你的循环代码,i 在哪里用的?如果你用了类似 allimg[i],那就是 3 楼说的块级作用域问题,改 var 为 let 应该就行。
nitmali
281 天前
var 换 let
cheese
281 天前
var allimg = 获取到的图片数组;
var oldcontent = 原内容;

// 将每个异步操作转换为 Promise
var promises = allimg.map(function(img) {
return new Promise(function(resolve, reject) {
$.post('url', 参数, function(ret) {
if (ret['code'] == 200) {
resolve({oldimgurl: ret['oldimgurl'], newimgurl: ret['newimgurl']}); // 成功时解析新旧 URL
} else {
reject(错误信息);
}
}, 'json');
});
});

// 等待所有 Promise 完成
Promise.all(promises).then(function(results) {
// 此处的 results 是一个包含所有成功替换 URL 信息的数组
results.forEach(function(result) {
oldcontent = oldcontent.replace(result.oldimgurl, result.newimgurl);
});
}).catch(function(error) {
console.log(error); // 处理任何一个请求失败的情况
});
zzxqd
281 天前
@abccccabc 那要按你这么说的话,其实不用考虑那么多,你现在的应该就满足了

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

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

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

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

© 2021 V2EX