Vấn đề đồng bộ dữ liệu với nodejs



  • Ai cũng biết bất đồng bộ là ưu thế tốc độ với nodejs nhưng mà với beginner như mình thì cũng khá căng thẳng.
    Đại loại mình có 1 func để validate chút dữ liệu và mình cần nó return true hoặc false để xác thực đầu vào như thế này ạ:

    validateToken: function(req, res, next) {
        var token = req.body.token;
        if (!token) {
            res.send({ code: 400, error: res.__('api.auth.error.tokenrequired') });
        }
        else {
            // Set DB
            AuthModel.setDB(req.db);
    
            // Check token
            AuthModel.getlist(function (err, records) {
                if (records.length == 0) {
                    res.send({ code: 400, error: res.__('api.auth.error.tokeninvalid') });
                } else {
                    return true;
                }
            }, { token: token });
        }
        return false;
    }
    

    Mình test thử mà nó chưa chạy đoạn if else đã chạy đến đoạn cuối và return false rùi.
    E có áp dùng module sync nhưng chưa bít cách code lắm!.
    Bạn nào biết chỉ giáo mình chút với ạ.
    Thanks all!


  • Global Moderator

    Chơi với Async thì code cũng phải được thiết kế dạng async bạn ạ :D Tức là thay vì sử dụng return thì bạn cần phải gọi hàm callback khi thực hiện xong 1 tác vụ async.

    Bạn đọc thêm các bài sau đây để hiểu bản chất hơn, tránh gặp phải những lỗi tương tự:

    https://techmaster.vn/posts/33416/hoc-lap-trinh-web-javascript
    https://techmaster.vn/posts/33344/lap-trinh-nodejs-co-ban-den-nang-cao


  • Global Moderator

    Mình nhớ @Rik-Ky có 1 bài rất hay về không đồng bộ, nhưng tìm không ra. Sẽ rất tuyệt nếu như bạn được đọc bài viết đó. Ko biết có bác nào có link ko ? :D



  • @Tieu-dang-van bạn nên dùng module Async để làm việc với cơ sở dữ liệu trong nodejs.


  • Banned

    @Vũ rảnh Tùng sẽ lục cái DB xem còn ko. Thanks



  • Mình cũng biết là phải áp dùng sync vào rùi nhưng mà thực tế chưa quan với câu cú của nodejs lắm nên chưa biết cách bố trí thế nào cho hợp lý và chuẩn.
    Mọi ng có thể chỉ rõ hơn được không ạ?
    Thanks all!



  • Là 1 routes validateToken: function(req, res, next)
    Thì sao lại return true, false bạn.
    Với format lại code đi kìa.



  • @Tieu-dang-van block code nào xác định phải đồng bộ thì cả block đó nên dùng đồng bộ.
    Ví dụ đoạn code của bạn có vấn đề như sau :

    alidateToken: function(req, res, next) {
      var token = req.body.token;
    // block if else   vì trả lại kết quả chậm hơn`  return false `nên hàm alidateToken sẽ nhận giá trị false; 
      if (!token) {
        res.send({
          code: 400,
          error: res.__('api.auth.error.tokenrequired')
        });
      } else {
        // Set DB
        AuthModel.setDB(req.db);
    
        // Check token
        AuthModel.getlist(function(err, records) {
          if (records.length == 0) {
            res.send({
              code: 400,
              error: res.__('api.auth.error.tokeninvalid')
            });
          } else {
            return true; // ~?
          }
        }, {
          token: token
        });
      }
      return false; // trả về false cho alidateToken = > kết thúc khối lệnh alidateToken; , bên cạnh đó đoạn này sẽ là viết SAI nếu bạn đang dùng express để làm router điều hướng, trả về false sẽ khiến toàn bộ router của bạn bị loop redirect.
    }
    

    Nodejs là bất đồng bộ (nhiều tác vụ chạy song song,), còn hầu hết các ngôn ngữ khác là đồng bộ. Với ngôn ngữ lập trình đồng bộ, block if else của bạn sẽ thực hiện hết rồi mới đến return false, với nodejs do thực hiện song song, tác vụ nào trả về kết quả trước sẽ được ưu tiên trước. Vì vậy code của bạn nếu muốn viết đúng phải dùng module async hoặc bluebird hoặc Q để áp chế cái bất đồng bộ của JS, hoặc ảo diệu nhất là dùng callback hell (nếu code đơn giản thì hell là heo thôi, còn code phức hợp thì welcome to the HELL<nodejs> ) . Do đó code của bạn nên viết lại như sau:

    var async = require('async');
    //... stuff ..
    alidateToken: function(req, res, next) {
      var token = req.body.token;
      if (!token) {
        return res.send({
          code: 400,
          error: res.__('api.auth.error.tokenrequired')
        });
      } else {
     // toàn bộ block cần áp chế đồng bộ
        async.waterfall([
          function(callback) {
            // Set DB
            AuthModel.setDB(req.db);
            // Check token
            AuthModel.getlist(function(err, records) {
              if (err) return callback(err,null);
              if (records.length == 0) {
                return callback(err,null);
              } else {
                return callback(null,true);
              }
            }, {
              token: token
            });
          }
        ], function(err, result) {
          if (err) {
            return res.send({
              code: 400,
              error: res.__('api.auth.error.tokeninvalid')
            });
          };
          return res.send({msg:'token is valid.'})
        });
    
      }
      //return false; // 
    }
    


    1. Cái validateToken của bạn là một middleware thì bạn cần return next() hoặc trả về kết quả ngay và không cho phép next đến route đứng sau.
    2. Trong if else của bạn, bạn không sử dụng return res.send({...}) nên validateToken không dừng lại khi res.send đã chạy xong nên return false; ở cuối cùng luôn chạy.

    Bạn có thể thay return false thành else return false để kiểm tra thử trước. Mình đang nghĩ vấn đề bạn gặp phải không phải vấn đề đồng bộ hay bất đồng bộ mà code chưa tối ưu. Hãy hạn chế sử dụng các thư viện async và kể cả ES6 promise hay mấy cái thứ đại loại như vậy, nó chỉ làm code của bạn thêm rối.

    Dừng lại 1 chút và đọc bài viết về callback này trước khi bạn tiếp tục code.

    “What I Cannot Create, I Do Not Understand”

    0

Log in to reply