Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 异步/等待的多次迭代在for循环中无法正常工作_Javascript_Node.js - Fatal编程技术网

Javascript 异步/等待的多次迭代在for循环中无法正常工作

Javascript 异步/等待的多次迭代在for循环中无法正常工作,javascript,node.js,Javascript,Node.js,我已经在下面编写了一些代码来隔离我遇到的问题 我试着按顺序发送每个帖子:一个接一个。第二个请求似乎没有完成,即使我删除了超时。(无论如何,服务器响应非常快) 我尝试过不同的方法,比如将异步移到更高的范围,使用承诺(这会丢失顺序行为),但都没有成功 为什么会发生这种情况 编辑:将waitget.post(…)替换为 wait new Promise(r=>setTimeout(r,2000))我看到每个睡眠都是按顺序发生的(一个接一个),这正是我想要的。谜题的最后一个部分是为什么这不适用于GET库

我已经在下面编写了一些代码来隔离我遇到的问题

我试着按顺序发送每个帖子:一个接一个。第二个请求似乎没有完成,即使我删除了超时。(无论如何,服务器响应非常快)

我尝试过不同的方法,比如将异步移到更高的范围,使用承诺(这会丢失顺序行为),但都没有成功

为什么会发生这种情况

编辑:将wait
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) 
    } 
}