Javascript 异步/等待的多次迭代在for循环中无法正常工作
我已经在下面编写了一些代码来隔离我遇到的问题 我试着按顺序发送每个帖子:一个接一个。第二个请求似乎没有完成,即使我删除了超时。(无论如何,服务器响应非常快) 我尝试过不同的方法,比如将异步移到更高的范围,使用承诺(这会丢失顺序行为),但都没有成功 为什么会发生这种情况 编辑:将waitJavascript 异步/等待的多次迭代在for循环中无法正常工作,javascript,node.js,Javascript,Node.js,我已经在下面编写了一些代码来隔离我遇到的问题 我试着按顺序发送每个帖子:一个接一个。第二个请求似乎没有完成,即使我删除了超时。(无论如何,服务器响应非常快) 我尝试过不同的方法,比如将异步移到更高的范围,使用承诺(这会丢失顺序行为),但都没有成功 为什么会发生这种情况 编辑:将waitget.post(…)替换为 wait new Promise(r=>setTimeout(r,2000))我看到每个睡眠都是按顺序发生的(一个接一个),这正是我想要的。谜题的最后一个部分是为什么这不适用于GET库
get.post(…)
替换为
wait new Promise(r=>setTimeout(r,2000))
我看到每个睡眠都是按顺序发生的(一个接一个),这正是我想要的。谜题的最后一个部分是为什么这不适用于GET库
const got = require('got')
const FormData = require('form-data')
const fs = require('fs')
var f = new FormData();
f.append('password', 'wrong')
f.append('swupdate.swu', fs.createReadStream('./fake.swu'))
postFormToIPs(
f
);
async function postFormToIPs(form){
for (let i = 0; i < 2; i++){
console.log(i);
const { body } = await got.post('http://postman-echo.com/post', {
body: form,
timeout: 5000
});
console.log(body)
}
}
我想看看
0
server response
1
server response
编辑:
我认为在第一个请求返回响应后,文件流将关闭。添加多个文件流解决了这个问题,但理想情况下我只使用一个。这是我目前拥有的最佳解决方案。我会通过重用相同的文件流来改进它,但我不确定这是否可行
async function postFormToIPs(){
for (let i = 0; i < 2; i++){
console.log(i);
var f = new FormData();
f.append('password', 'wrong')
f.append('swupdate.swu', fs.createReadStream('./fake.swu'))
const { body } = await got.post('http://postman-echo.com/post', {
body: f
});
console.log(body)
}
}
异步函数postFormToIPs(){
对于(设i=0;i<2;i++){
控制台日志(i);
var f=新的FormData();
f、 追加('密码','错误')
f、 追加('swupdate.swu',fs.createReadStream('./false.swu'))
const{body}=wait-got.post('http://postman-echo.com/post', {
正文:f
});
控制台日志(正文)
}
}
对于解决方案,您的想法是正确的,但最好了解这里实际发生的情况以及导致问题的原因
NodeJS
的FormData
实现与在浏览器中的工作方式不同。如果您查看表单数据
包的实现,您将看到表单数据
就像一个可读的流,它写入http请求(在本例中,
get
post请求)。FormData
中的值将逐个写入请求,直到没有剩余值为止。然后从FormData
中清除值(您可以在FormData.\u streams
下看到这种情况)。然后,将FormData
视为released
(由内部属性定义),以防止它写入任何其他请求
通过使用调试器
或在发出第一个请求前后记录FormData
对象,可以看到所有这些情况。您仍然可以将其他值附加到FormData对象,但无法将这些属性写入请求对象。这就是导致第二个请求挂起的原因
一个接一个地发出这些请求的正确方法是为每个请求创建一个新的FormData实例,并向其附加相同的值
对于文件流,只要将其分配给变量,就可以保持该文件流处于打开状态,并重用相同的流
constfilestream=fs.createReadStream('./false.swu');
异步函数postFormToIPs(){
对于(设i=0;i<2;i++){
控制台日志(i);
var f=新的FormData();
f、 追加('密码','错误')
f、 追加('swupdate.swu',fileStream)
const{body}=wait-got.post('http://postman-echo.com/post', {
正文:f,
超时:5000
});
控制台日志(正文)
}
}
我看到您的端点是/update
。你是否应该使用got.put
而不是post?好吧,我不确定你说的“按顺序发布请求,这样我就不会打开太多连接”是什么意思。但如果这意味着你希望它们一个接一个地发送,我可以告诉你,等待的for循环不会这样做,node将在不等待任何东西的情况下通过for循环,并在彩信中触发所有请求,当它们解析时,您将获得结果,因此就像所有请求都在同一时间触发一样,@abney317,很遗憾,没有。Web服务器只有/update响应post请求,但是在开发服务器api时,我会记住这个约定。@ChamsddineBouzaine我看到的行为表明每个事件都是在另一个事件之后触发的。我已经通过使用“wait new Promise(r=>setTimeout(r,2000))”一行代码确认了这种行为。如果我要将post请求移动到(async()=>{})中;结束语我会看到你描述的类似行为,我认为这更典型,但不是我想要的。我可以在控制台输出中添加一些时间戳来让这一点更清楚。感谢您对为什么会发生这种情况的深入了解。干杯
async function postFormToIPs(){
for (let i = 0; i < 2; i++){
console.log(i);
var f = new FormData();
f.append('password', 'wrong')
f.append('swupdate.swu', fs.createReadStream('./fake.swu'))
const { body } = await got.post('http://postman-echo.com/post', {
body: f
});
console.log(body)
}
}