Возникла проблема с синхронной работой в NodeJS - PullRequest
0 голосов
/ 18 января 2019

В приведенном ниже коде есть 2 файла и файл client.js, который вызывает файл сервера, но не получает синхронный вывод. Я попытался с обещанием, 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

Ответы [ 5 ]

0 голосов
/ 18 января 2019

Как и во время НИОКР, модуль запроса не возвращается обещание, поэтому для этого нужно использовать библиотеку запроса-обещание.

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();
0 голосов
/ 18 января 2019

Вы можете использовать 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();
0 голосов
/ 18 января 2019

Как альтернатива импорту дополнительных библиотек. Вы можете просто «обещать» метод 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()
0 голосов
/ 18 января 2019

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]);
    }
}

здесь все запросы выполняются одновременно и возвращаются в неопределенном порядке.

Что вам нужно сделать, если вы хотите использовать async, это сделать запрос верным обещанием. Под капотом await на самом деле просто делает request.then (что-то Else ()). Так что если вы измените свой запрос, чтобы вернуть обещание, как:

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

Ваш код ожидания будет работать, как и ожидалось. Эффективно это делает.

request('a').then(() => request('b')).then(() => request('c'));

0 голосов
/ 18 января 2019

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

Поскольку вы сами формируете строку данных формы через узел

Возможно ли, что если вы просто позволите request помочь вам сформировать закодированную строку с помощью их метода формы?

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

...