如何在每个项目上运行同步POST?

时间:2018-08-28 13:08:51

标签: javascript node.js

arr说,我有一个数组,我需要对其进行迭代。

到目前为止我尝试过的事情:

arr.forEach((rack) => {
    request.post({
        headers: {'content-type' : 'application/x-www-form-urlencoded'},
        url:     'https://example.com/render',
        body: "target=foobar"
    }, function(error, response, data){
        if (error) {
            console.err(error);
        } else {
            console.log(JSON.stringify(data, null, 4));
        }
    });
});

我没有输出,也没有错误。

奖励问题:我可以从全局范围内的帖子中返回一个值吗?

3 个答案:

答案 0 :(得分:1)

问题的第一部分是因为请求是异步的,因此您需要完成forEach循环并在调用完成之前退出。

对于第二部分,您可以使用promise基本等待查询结果。代码

function getPromise(url) {
    return new Promise((resolve, reject) => {
        request.post({
            headers: {'content-type' : 'application/x-www-form-urlencoded'},
            url:     'https://example.com/render',
            body: "target=foobar"
            }, function(error, response, data) {
                if(error) {
                    reject(error)
                } else {
                    resolve(JSON.stringify(data, null, 4))
                }
            })
        })        
}

var promiseArray = arr.map((rack) => getPromise(rack))
Promise.all(promiseArray).then((value) => {
    console.log('I am done');
})

将是您想要的。您可以分配回全局范围值(尽管不建议这样做)

答案 1 :(得分:1)

一种解决方案是将其包装在promise中:

for rack of arr {
    try {
        const result = await new Promise((res, rej) => {
            request.post({
                headers: {'content-type' : 'application/x-www-form-urlencoded'},
                url:     'https://example.com/render',
                body: "target=foobar"
            }, function(error, response, data){
                if (error) {
                    rej(error);
                    console.err(error);
                } else {
                    res(data);
                }
            });
        });
        console.log(JSON.stringify(result, null, 4));
    } catch(err) {
        console.log(err);
    }
}

答案 2 :(得分:1)

forEach是严格同步的,并且通常已过时,因为它不支持生成器,而循环语句则支持async..await。可以使用async..awaitrequest-promise(它们是request的官方承诺副本)来完成:

// within async function
for (const rack of arr) {
    try {
        const data = await request.post({
            headers: {'content-type' : 'application/x-www-form-urlencoded'},
            url:     'https://example.com/render',
            body: "target=foobar"
        });
        console.log(JSON.stringify(data, null, 4));
    } catch (error) {
        console.err(error);
    }
}

由于请求彼此不依赖,因此可以与Promise.all并行执行。

  

我可以从全局范围内的帖子中返回值吗?

这是this infamous problem的特例。异步调用中的值不能以同步方式使用,这会将异步控制流扩展到所有调用堆栈,可能一直扩展到入口点:

(async () => {
  const result = await asyncFn();
})().catch(console.error)