【问题标题】:NodeJS asynchronous.end() not working on POST requestNodeJS asynchronous.end() 不适用于 POST 请求
【发布时间】:2017-12-29 17:11:50
【问题描述】:

我正在尝试根据数据库查询返回文本 - 用于帐户注册 - 在 $.ajax success' 参数上,经过多次搜索,我无法获得下面的代码有什么问题。

我找不到如何发送需要异步功能的http响应,如果我尝试这样做,则根本不会处理或检测到请求。

我认为问题在于我的 res.end("false") 调用没有及时调用,但代码对我来说看起来是正确的。

我不想使用 express 并且所有回调都正常工作但是我确定问题出在 server.js 我放评论的地方

客户端:

$.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.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);
    });
}

最后编辑:简而言之,

这是我不删除最后一行时得到的结果(正常行为但我无法获得异步响应

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

但是当我删除最后一个 response.end('oko') 时,OPTIONS 之后的所有内容都不会出现...

【问题讨论】:

  • if (!exist) { saveData(new_data); } 如果没有现有帐户,您会将响应发送到哪里?不在 saveData() 中。我假设它是由您要删除的response.end( 'oko' ) 行发送的,所以您尝试过if (!exist) { saveData(new_data); response.end( 'oko' ); }
  • 我猜你的编辑解释了它。
  • 如果我删除 response.end('oko');该请求不再处理,但是,使用上面的代码,我在 isExist() 附近进行的所有 response.end 调用都不会执行,即使我删除了最后一个......
  • 你找到它停止的地方了吗?您是否仍然看到console.log(exist); 您是否还有一个具有模式 account_registration 的主体?您是否尝试将所有内容包装到 try/catch 中以检查错误?很抱歉这些问题,但是这台机器上没有 mongo 或 mongoose,所以不能自己测试看看它停在哪里。
  • 它在 server.js console.log(request.method) 的第一行之一之前停止;在正常执行中,我在日志中得到了 OPTIONS 和 POST,但如果我删除最后一个响应,我只会得到 OPTIONS,就像其他调用没有及时发送一样......

标签: javascript jquery node.js http request


【解决方案1】:

我现在明白这个问题了。

您正在发出 CORS 请求。所有 CORS 请求都会先向服务器发送一个 OPTIONS 请求,然后再发送实际请求以检查访问控制标头是否真的允许服务器处理该请求。

由于您的请求处理程序检查是否存在 body.pattern,而 OPTIONS 请求不存在该 body.pattern,因此永远不会发送响应。

因此请求永远不会得到响应,并且您的 POST 请求永远不会到达服务器,因为它没有从 OPTIONS 请求中获得这样做的权限。

因此,如果您添加 if ( method === 'OPTIONS' ) { response.end() } else if ( body ) { ... } 之类的内容,您将确保这些选项将得到处理。

为了安全起见,请确保所有请求都得到答复,即使您只是回答错误或 404。

【讨论】:

  • 这是我需要的答案,哇,谢谢,它现在可以正常工作了,不敢相信它真的这么简单,但是你能解释一下为什么“同步”响应(就像 server.js 的最后一行) 在没有处理 OPTIONS 请求的情况下成功发回?
  • 因为您使用 var body = ''; 手动创建主体并让 on( 'data' ) 向其中添加内容(这不是属性模式),以便满足 if ( body ) 检查,但不是if (body.pattern ) 检查。所以 OPTIONS 请求将进入if body 部分,然后由response.end('oko'); 结束。然后,当您删除该 response.end('oko'); 时,不会发送响应。如果您不自己构建正文,而是尝试直接使用 POST 请求中的正文,您会很快收到错误,因为 OPTIONS 无法满足 if ( body )
  • 由于大多数类型的请求 OPTIONS、GET、POST 等会得到不同的处理,我通常将所有特定功能包装在方法检查中。所以我只会定义一个主体并向它添加数据,因为请求是一个 POST 请求。
  • 我确信它与 response.end() 的放置有关,就像我不得不在某处放置另一个回调但我只是忘记处理 OPTIONS 请求,感谢一百万次,我'我从来没有弄清楚自己!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-03
  • 2014-09-05
  • 1970-01-01
  • 2022-01-21
  • 2017-08-06
  • 1970-01-01
  • 2013-03-02
相关资源
最近更新 更多