【问题标题】:Facing issue for synchronous operation in NodeJSNodeJS中的同步操作面临的问题
【发布时间】:2019-06-12 11:15:12
【问题描述】:

下面的代码有 2 个文件,并且有 client.js 调用服务器文件但没有得到同步输出。 我尝试了promise、bluebird、async_await,但没有成功。 预期输出是控制台中的字母序列。

不要使用 settimout。

了解文件。 server.js : 服务器文件有 NodeAPI,它的内容只路由。

Client.js : 尝试的逻辑在这个文件中

您需要使用两个控制台,首先运行 server.js,第二个控制台需要运行 client.js,输出将在 server.js 控制台中打印。

 Expecting output is 
    a
    b
    c
    d
    e

 /////////////////server.js/////////////////
    var express = require('express');
    var bodyParser = require('body-parser')
    var app = express();

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({
        extended: true
    }));

    app.post('/', function (req, res) {   
       console.log(req.body.test)
       res.status(200).send('ok');
    });

    var server = app.listen(3000, function () {
        console.log('ok');
    });

    //////////////client.js///////////////////


    //var Promise = require('bluebird');
    var request = require('request');
    console.log('server file called');
    var array_data = ['a', 'b', 'c', 'd', 'e'];


    // var promises = [];
    // for(let i = 0; i < array_data.length; i++) {
    //     var promise = request.post({url: 'http://localhost:3000',form : {key:array_data[i]}});
    // }

    // var page = 0;
    // var last_page = array_data.length;

    // (function loop() {
    //     if (page < last_page) {
    //         request.post({
    //             url: 'http://localhost:3000',
    //             form: 'test=' + array_data[page]
    //         }, function (error, response, body) {
    //             page++;
    //             loop();
    //         });
    //     }
    // }());


    // async function loopAsync() {
    //     for (let i = 0; i < array_data.length; i++) {
    //         await request.post({
    //             url: 'http://localhost:3000',
    //             form: 'test=' + array_data[i]
    //         });
    //     }
    // }
    // loopAsync();

    async function loopAsync() {
        var page = 0;
        var last_page = array_data.length;
        while (page < last_page) {
            await request.post({
                url: 'http://localhost:3000',
                form: 'test=' + array_data[page]
            });
            page++;
        }
    }
    loopAsync();


[enter image description here][1]


  [1]: https://i.stack.imgur.com/WVlut.png

【问题讨论】:

  • 您可以将 await 与 promise 一起使用,因此请使用 request-promise npmjs.com/package/request-promise#request-promise
  • 嗨@Ariz,我已经尝试过承诺请求但没有成功。
  • @Ariz 是对的,您只能将 await 与返回承诺的函数一起使用,请求本身不会这样做。你能分享一下你在 request-promise 中使用的代码吗?
  • 我要做的第一件事是使用 NPM 调试断点来确保请求按预期顺序分派,这将排除客户端的任何问题。

标签: node.js promise async-await bluebird


【解决方案1】:

https://github.com/request/request#forms

由于您是通过 Node 自己形成表单数据字符串

如果你可以让request通过他们的form方法帮助你形成编码字符串,是否有可能?

const jobs = [];
const array_data = [
  'a',
  'b',
  'c',
  'd',
  'e',
];
require('request');
const request = require('request-promise');
async function loopAsync() {
  for(const char of array_data) {
    jobs.push(
      request.post({
          url: 'https://marble-scene.glitch.me/',
          form: {
            test: char
          }
      })
    );
  }
  const output = await Promise.all(jobs);
  output.forEach(char => console.log(char)); // # a b c d e
}
loopAsync();

[编辑]

只需编辑client.js 代码,修复jobs.push 块内的愚蠢语法错误

工作证明:https://glitch.com/edit/#!/marble-scene

【讨论】:

  • 如果你的答案没有得到正确的输出,它似乎和我分享我的代码的过去一样
【解决方案2】:

作为导入其他库的替代方法。您可以简单地“承诺”依赖于回调的 request.post 方法。

async function loopAsync() {
        var page = 0;
        var last_page = array_data.length;
        while (page < last_page) {
            await new Promise((resolve, reject) => {
                request.post({
                  url: 'http://localhost:3000',
                  form: 'test=' + array_data[page]
                 }, function(err,httpResponse,body){
                   if (err) reject(err);
                   else resolve({httpResponse,body});
                 });
                 page++;
            });
        }
}
loopAsync()

【讨论】:

  • 谢谢您,您的回答是有效的,但希望深入了解您使用 async_await 和 promise,您能分享一下详细信息吗?
  • @nigammehta await 构造期望request.post 不会返回的承诺。通过将其包装在 Promise 调用函数中,您可以将其转换为返回 Promise 的函数,而 Promise 又是 await 构造所期望的。
  • 感谢分享请求承诺的深度。
  • 为此我使用了 request-promise 库并得到了另一个解决方案。
【解决方案3】:

request.post 是一个接受请求选项和回调的函数。

function request(letter, callback = () => {}) {
    setTimeout(() => {
        console.log(letter);
        callback();
    }, Math.random() * 1000);
}

您正在做的是在不提供回调的情况下调用该函数:

async function clientWithRequest() {
    const letters = ['a', 'b', 'c'];

    for(let i = 0; i < letters.length; i++) {
        await request(letters[i]);
    }
}

在这里,所有请求都同时被触发,并且会以不确定的顺序返回。

如果你想使用异步,你需要做的是让你的请求返回一个承诺。在后台,await 实际上只是在做 request.then(somethingElse())。因此,如果您更改请求以返回如下承诺:

function requestPromise(letter) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(letter);
            resolve();
        }, Math.random() * 1000);
    });
}

然后您的等待代码将按预期工作。实际上它正在做。

request('a').then(() =&gt; request('b')).then(() =&gt; request('c'));

【讨论】:

  • setTimeout 不允许使用,它无法根据服务器操作得到正确的响应
  • @nigammehta Will Munn 举了一个例子来证明他关于异步操作的观点。如果您想使用 async 和 await 将 yourrequest.post 函数包装在一个 promise 中,如示例中所示
  • 是的,这只是一个例子,正如@Joseph Persie 在他的回答中所说,您可以使用 promisify 和 request.post 来实现这一点,或者使用 request-promise 模块
【解决方案4】:

你可以使用 util.promisify。

这里是示例代码

const reqpost = util.promisify(request.post); 

async function loopAsync() {
    var page = 0;
    var last_page = array_data.length;
    while (page < last_page) {
      await reqpost({
        url: 'http://localhost:3000',
        form: 'test=' + array_data[page]
      });
     page++;
 } } 

loopAsync();

【讨论】:

    【解决方案5】:

    正如我所做的研发一样,请求模块没有返回承诺,因此需要使用 request-promise 库。

    let request = require('request');
        let rp = require('request-promise');
        var array_data = ['a', 'b', 'c', 'd', 'e'];    
        //with the use of request-promise library 
            async function loopAsync() {
                var page = 0;
                var last_page = array_data.length;
                while (page < last_page) {
                    var options = {
                        method: 'POST',
                        uri: 'http://localhost:3000',
                        body: {
                            test: array_data[page]
                        },
                        json: true // Automatically stringifies the body to JSON
                    };
                    await rp(options);
                    page++;
                }
            }
            loopAsync();
    

    【讨论】:

      猜你喜欢
      • 2019-10-17
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      • 2020-03-10
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多