【问题标题】:make NodeJS function synchronus? sends json response before querying database使Node JS函数同步?在查询数据库之前发送 json 响应
【发布时间】:2018-05-08 01:38:27
【问题描述】:

我正在使用 nodejs 作为后端语言来制作登录/注册 Android 应用程序 UI。发生的事情是,每当我单击注册按钮时,它会在查询数据库之前发送 json 响应(选择语句以检查用户名是否存在)导致 android 应用程序得到错误的响应,这导致我单击按钮两次以注册正确回复。例如,假设他们是数据库中名为 test 的用户名,我尝试使用用户名 test 进行注册,它会告诉我该用户名已被占用,如果擦除测试并输入,可以说“bob”,它不存在数据库它仍然说用户名已经被使用,即使它不是但是当我再次点击注册按钮时它会注册用户。我假设这是因为它是异步的(它在查询数据库时或之前发送 json 响应)。我怎样才能使这个同步或有其他方法来解决这个问题?

服务器文件:

var express = require('express');
var app  = express();
var bodyParser = require('body-parser');
var mysql = require('mysql');

//connection
var con = mysql.createConnection({
    host: "localhost",
    user: "root",
    password: "password",
    database : "androidtest"
});

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

//declare variables to hold values entered by the user
var name;
var username;
var password;
var age;

//boolean array to let frontend know what is going on
var response;

app.post('/', function(req, res) {
    //retrieve variables
    username = req.body.username;
    name = req.body.name;
    age = req.body.age;
    password = req.body.password;

    //query database
    //check if username is taken
    var select = "SELECT * FROM users WHERE username = ? LIMIT 1";
    con.query(select, [username], function (err, results) {
        if (err) throw err;
        //if username is taken send json string 'exists' to android app
        if(results.length) {
            response = {"exists" : "true"};     
        //if username is available send string 'success' and add the user to the database
        } else {
            var add = "INSERT INTO users (name, username, age, password) VALUES (?, ?, ?, ?)";
            response = {"success" : "true"};
            con.query(add, [name, username, age, password]);
            if (err) throw err;
            console.log('row inserted');
        }
    });
    //send json
    res.json(response);
    //prevents the functions from being executed more than once
    res.end('/');
});
//listen on port 3000
app.listen(3000);

android 应用程序 java:

bRegister.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        final String name = etName.getText().toString();
        final String username = etUserName.getText().toString();
        final String password = etPassword.getText().toString();
        final int age = Integer.parseInt(etAge.getText().toString());

        Response.Listener<String> responseListener = new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONObject jsonResponse = new JSONObject(response);
                    //Boolean exists = jsonResponse.getBoolean("exists");
                    String exists = jsonResponse.getString("exists");
                    if (exists.matches("true")) {
                        Toast toast = Toast.makeText(getApplicationContext(), "username already exists", Toast.LENGTH_SHORT);
                        toast.show();
                    }
                } catch(Exception e) {
                    e.printStackTrace();
                }
                try {
                    JSONObject jsonResponse = new JSONObject(response);
                    //Boolean success = jsonResponse.getBoolean("success");
                    String success = jsonResponse.getString("success");
                    if (success.matches("true")) {
                        Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
                        RegisterActivity.this.startActivity(intent);
                    } else {
                        AlertDialog.Builder builder = new AlertDialog.Builder(RegisterActivity.this);
                        builder.setMessage("Register Failed")
                                .setNegativeButton("Retry", null)
                                .create()
                                .show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        };

        RegisterRequest registerRequest = new RegisterRequest(name, username, age, password, responseListener);
        RequestQueue queue = Volley.newRequestQueue(RegisterActivity.this);
        queue.add(registerRequest);
    }
});

}

【问题讨论】:

  • 这里有几百个这样的帖子。将res.json(...) 放入数据库回调中,以便仅在您实际拥有数据时触发。而且,在res.json() 之后不需要res.end()
  • 确实有效,我在问问题之前尝试过,但我使用 console.log 来显示检索到的变量,并且它们被显示不止一次,并且它们也被添加到数据库中超过一次,所以我添加了 res.end() 导致显示并仅添加到数据库一次。但是,现在我没有使用 console.log(),而且它们似乎没有被多次添加到数据库中
  • 我的回答对您有帮助吗?现在可以用了吗?
  • 是的,现在可以了

标签: java android node.js rest express


【解决方案1】:

你必须放

res.json(...);
res.end('/');

在以下行的右括号之后(在 else 块的 & 之后):

console.log('row inserted');

然后它首先在查询完成时执行。

【讨论】:

    猜你喜欢
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    相关资源
    最近更新 更多