Handle multiple users requests to multiple remote

2019-05-29 09:51发布

问题:

I created a ExpressJS application using NightmareJS which has a form and when we fill form and submit, it sends requests to some remote forms and calculate data and return those results. But the problem is it only works when single client submit the form. When multiple clients submit the form at same time it doesn't work. What could be the reason for this and how to solve this?

Front end JS script

$(document).ready(function () {

$("#calculate-form").submit(function (event) {
    var request;

    if (request) {
        request.abort();
    }

    var $form = $(this);

    var $inputs = $form.find("input, select, button, textarea");

    var serializedData = $form.serialize();

    $inputs.prop("disabled", true);

    form1(request, serializedData, $inputs, '/example1', '#form1');

    function form1(request, serializedData, inputs, appUrl, displayElement)
    {
        request = $.ajax({
            url: appUrl,
            type: "post",
            data: serializedData
        });



        request.done(function (response) {
            $(displayElement).text(response.value);

            form2(request, serializedData, $inputs, '/example2', '#form2');

            function form2(request, serializedData, inputs, appUrl, displayElement)
            {
                request = $.ajax({
                    url: appUrl,
                    type: "post",
                    data: serializedData
                });

                request.done(function (response) {
                    $(displayElement).text(response.value);
                });

                request.fail(function (jqXHR, textStatus, errorThrown) {
                    console.log("Failed");
                });
            }
        });

        request.fail(function (jqXHR, textStatus, errorThrown) {
            console.log("Failed");
        });
    }

    event.preventDefault();
});
});

ExpressJS index script

var express = require('express');
var app = express();
var phantom = require('phantom');
var bodyParser = require('body-parser');
var Nightmare = require('nightmare');

app.use(bodyParser.urlencoded({
  extended: true
}));
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/'));
app.engine('html', require('ejs').renderFile);
app.get('/', function (request, response) {
   response.render('index.html');
});
app.listen(app.get('port'), function () {
   console.log('Scrapper is running on port', app.get('port'));
});

require('./form1')(app, Nightmare);
require('./form2')(app, Nightmare);

ExpressJS form1 script

module.exports = function (app, Nightmare) {

var nightmare1 = Nightmare({
    show: true
});


app.post('/example1', function (req, res) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.setHeader('Content-Type', 'application/json');
    try
    {
        if (req.method === 'POST') {
            var requestParams = req.body;
            nightmare1

                    .goto('https://example1.com/form')
                    .evaluate(function () {
                        var select = document.querySelector('#RepaymentMethod');
                        select.value = "1";
                        select.dispatchEvent(new Event('change'));
                    })
                    .wait("#formbtn-1")
                    .evaluate(function () {

                        document.getElementById('inputfield_1').value = "inputfield-1-Value";

                        document.getElementById('btnSubmitform').click();

                    })
                    .wait("#resultvalue")
                    .evaluate(function () {

                        var str = document.querySelector('#resultvalue').innerText;
                        return res;

                    })
                    .end()


                    .then(function (form1) {
                        res.send({value: form1});
                        nightmare1.halt();
                    })

                    .catch(function (error) {
                        res.send({'error': error});
                        nightmare1.halt();
                    });
        }
    } catch (err)
    {
        res.sendStatus(400).send(err);
        nightmare1.halt();
        process.exit();
    }
});
}

ExpressJS form2 script

module.exports = function (app, Nightmare) {

var nightmare2 = Nightmare({
    show: true
});


app.post('/example2', function (req, res) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.setHeader('Content-Type', 'application/json');
    try
    {
        if (req.method === 'POST') {
            var requestParams = req.body;
            nightmare2

                    .goto('https://example2.com/form')
                    .evaluate(function () {
                        var select = document.querySelector('#RepaymentMethod');
                        select.value = "10";
                        select.dispatchEvent(new Event('change'));
                    })
                    .wait("#formbtn-1")
                    .evaluate(function () {

                        document.getElementById('inputfield_1').value = "inputfield-1-Value";
                        document.getElementById('inputfield_2').value = "inputfield-2-Value";

                        document.getElementById('btnSubmitform').click();

                    })
                    .wait("#resultvalue")
                    .evaluate(function () {

                        var str = document.querySelector('#resultvalue').innerText;
                        return res;

                    })
                    .end()


                    .then(function (form2) {
                        res.send({value: form2});
                        nightmare2.halt();
                        process.exit();
                    })

                    .catch(function (error) {
                        res.send({'error': error});
                        nightmare2.halt();
                        process.exit();  
                    });
        }
    } catch (err)
    {
        res.sendStatus(400).send(err);
        nightmare2.halt();
        process.exit();
    }
});
}

回答1:

Based on the example you posted, you're trying to re-use the same Nightmare instance across multiple requests. This won't work as if you have multiple requests come in, the actions for the later requests will be added to the currently executing context. This is further complicated because you're also .end()ing the instance, rendering the Nightmare instance unusable after the initial request.

If you move the Nightmare instantiation into the Express post method, you will likely have better luck, but be careful: this method will not scale particularly well.