简体   繁体   中英

NodeJS asynchronous.end() not working on POST request

I am trying to return text based on database query - for account registration - on the $.ajax success' parameter, after many search, I can't get what is wrong with the code below.

I can't find how to send http response that require asynchronous function, if I try to do it, the request is not handled or detected at all.

I think that the problem is that my that res.end("false") call is not called in time, but the code looks correct to me.

I don't want to use express and all callback are working correctly however I'm sure the problem is on server.js where I put comment

client-side:

$.ajax({
     async: true,
     dataType: "text",
     type: 'POST',
     url: 'http://192.168.0.23:3000',
     data: JSON.stringify(account_info),
     contentType: 'application/json; charset=utf-8',
     success: function (res) {
         console.log('Account registration : ' + res);
     },
     complete: function (res) {
            console.log('Account registration complete : ' +  
            JSON.stringify(res));
     },
    error: function (err) {
        console.log(err.responseText)
    }
});

server-side:

server.js

const http = require('http');
var mongoose = require('mongoose');
var Visitor = require('./models/visitor.js');
var Account = require('./models/account.js');
var api = require('./controllers/api.js');
var isExisting = api.isExisting;
var saveData = api.saveData;
const port = 3000;

const server = http.createServer();
console.log('server is listening on ' + port);
server.listen(port);
server.on('request', function (request, response) {

    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Methods', 'POST');
    response.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    console.log(request.method);

    var body = '';

    request.on('data', function (data) {
        body += data;
    });

    request.on('end', function () {

        //In case there's content in the POST request
        if (body) {
            console.log('\nRequest content:' + body + '\n');
            body = JSON.parse(body);
            mongoose.Promise = global.Promise;
            mongoose.connect('mongodb://localhost/someDB', {
                useMongoClient: true
            });

            //Pattern = ACCOUNT_REGISTRATION
            if (body.pattern == 'account_registration') {
                var value = {
                    email: body.email
                }
                var new_data = new Account(Account.store(body));
                //Check if account_name or website URL already in db
                // exist returning the callback
                isExisting(Account, value, function (exist) {
                    console.log(exist);
                    if (!exist) {
                        saveData(new_data);
                        //If you dont remove this line, the request is not detected by nodeJS
                        response.end('true');

                    } else {
                        console.log('\nAccount already exist.');
                        //If you dont remove this line, the request is not detected by nodeJS
                        response.end('false');
                        mongoose.connection.close();

                        }

                    });
                }
            }
            //Here it's working good but If I remove this line it'll not handle the request at all
            response.end('oko');
        });
    });

api.js

// The API controller
var mongoose = require('mongoose');

//Send some new_data to db
exports.saveData = function (new_data) {
    //Data saving into MongoDB database
    new_data.save(function (err) {
        if (err) {
            throw err;
        }
        console.log('\nData successfully added.');
        // We need to disconnect now
        mongoose.connection.close();
    });
}

exports.isExisting = function (ModelName, value, callback) {
    ModelName.count(value, function (err, count) {
        if (err)
            throw err;
        if (count == 0)
            callback(false);
        else
            callback(true);
    });
}

LAST EDIT: In short,

This is what I get when I don't remove the last line (normal behavior but I can't get my asynchronous response

server is listening on 3000 
OPTIONS 
POST Request content:{"*****"}//real data already in db 
true //This is isExisting() callback
Account already exist. 

But when I remove the last response.end('oko'), everything after OPTIONS not appear...

I understand the issue now.

You're making a CORS request. And all CORS requests send an OPTIONS request first to the server before sending the actual request to check if the Access Control headers actually allow the request to be handled by the server.

Since your request handler checks for the existance of a body.pattern, which won't exists for a OPTIONS request, the response is never sent.

So the request never gets responded to and your POST request never reaches the server because it doesn't get permission to do so from the OPTIONS request.

So if you add something like if ( method === 'OPTIONS' ) { response.end() } else if ( body ) { ... } you'll assure that the options will get handled.

To be safe make sure that all requests get answered, even if you just answer with an error or a 404.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM