簡體   English   中英

我已經在嘗試初始化偽JavaScript類中的“ this”對象時遇到很多麻煩

[英]I'm having a lot of trouble trying to modify a “this” object from within a pseudo javascript class when it's already been initialized

向下滾動到這篇文章的底部,以查看解決方法/可能的解決方案。

僅用注釋在源代碼中進行解釋,這可能會更容易。 當前的問題是我無法弄清楚偽類如何協同工作來執行我要執行的任務(在下面的代碼中進行了解釋)。

該代碼分為3個文件:lead.js,router.js和db.js。

有很多代碼行,但大多數都是注釋。

[lead.js]

var bcrypt = require('bcrypt'),
    validators = require('../lib/validators'),
    utility = require('../lib/utility'),
    document = {};

var Lead = module.exports = function (db) {
  // Save a reference to the database.
  this.db = db;

  // Reference initial document.
  // This is totally wrong, not sure how to 'send' a variable to the constructor of a class
  // when I cannot add another param. Due to how I'm importing the db model, I won't know what
  // the document is until I fill out the form. I've also tried 'document' instead of 'Lead.document'.
  this.document = Lead.document;

  // Setup the document if it exists.
  // This also doesn't work.
  // Basically I want to be able to set up a document variable outside of this module (line #100),
  // Then pass it to this module after filling it up with values from a form.
  // Then based on what's been filled in, it would fix up (trim, convert to lower case)
  // some of the values automatically and default a few values that I'm not always going to pass.
  if (!document) {
    var salt = bcrypt.genSaltSync(10),
        hash = bcrypt.hashSync(utility.generatePassword(), salt);

    // Default values.
    if (!document.meta.createdAt) { this.document.meta.createdAt = Date.now(); }
    if (!document.login.password) { this.document.login.password = hash; }
    if (!document.login.role) { this.document.login.role = 'User'; }

    // Normalize a few values.
    this.document.login.email = document.login.email.toLowerCase().trim();
    this.document.contact.name.first = document.contact.name.first.trim();
    this.document.contact.name.last = document.contact.name.last.trim();
    this.document.contact.address.street = document.contact.address.street.trim();
    this.document.contact.address.city = document.contact.address.city.trim();
    this.document.contact.address.state = document.contact.address.state.trim();
    this.document.contact.address.zip = document.contact.address.zip.trim();
    this.document.contact.phone.home = document.contact.phone.home.trim();
  }
  // So in regards to the above code, the end result I'm looking for is...
  // I want to append some properties to the this.document reference when the document is empty (when I'm updating it, I won't set the document), 
  // and on new documents it will append a few default values/normalize all the fields.
};

Lead.prototype.validate = function(fn) {
  var errors = [];

  // Some validation rules I cut out to make this shorter.

  if (errors.length) return fn(errors);
  fn();
};

Lead.prototype.save = function(fn) {
  this.db.collection('leads', function(err, collection) {
    if (err) { fn(new Error({message: err})); }

    collection.insert(this.document, function(err, result) {
      return fn(err, result);
    });
  });
};

---

[route.js file]

  var db = require('../models/db');

  app.post('/register', function(req, res) {
    var data = req.body.lead || {};

    // Fill the document.
    var document = {
      meta: {
        host: req.headers.host,
        referer: req.headers.referer,
        createdIPAddress: req.connection.remoteAddress
      },
      login: {
        email: data.email
      },
      contact: {
        name: {
          first: data.first,
          last: data.last
        },
        address: {
          street: data.street,
          city: data.city,
          state: data.state,
          zip: data.zip
        },
        phone: {
          home: data.phone
        }
      }
    };

    // Write the document.
    db.lead.document = document;

    db.lead.validate(function(err) {
      if (err) {
        req.session.error = err;
        return res.redirect('back');
      }

      db.lead.save(function(err) {
        res.redirect('/register/success');
      });
    });
  });

---
[db.js]

var mongodb = require('mongodb'),
    server = new mongodb.Server('localhost', 27017),
    connection = new mongodb.Db('test', server);

connection.open(function(err, db) {});

module.exports =  {
  lead: new (require('./lead'))(connection)
};

當我運行此命令時,驗證程序將始終報告密碼為空,這很有意義。 我最初使用空密碼將文檔發送給類(密碼是隨機生成的,而不是表單字段)-問題是我不知道如何處理if(!document)...代碼塊正確地設置this.document。

我希望在注釋和代碼之間您可以了解我要做什么。 我已經堅持了一段時間。

編輯

我稍微改變了流程以獲得解決方案。

在db.js中,我導出了連接,而不是直接實例化線索(和將來的模型)。

在router.js文件中,我需要db和Lead文件,然后在Lead的構造函數中傳遞db連接和文檔。 防爆。

var lead = new Lead(db, document);

在lead.js文件中,它變得像執行this.document = document(與db一樣)一樣簡單。 當我提交新線索時,我沒有從router.js發送的值會附加到文檔中(創建日期,隨機密碼等),一切都很好。

這是處理這個問題的一種體面的方法,還是有一種更好的方法來重構它?

即使使此代碼按需工作,這也是完全錯誤的方法。 在此示例中,您具有單身領導。 通過請求/ register url,您想要將'document'字段設置為此單例。 (重要)但是請求異步工作。 絕對不能保證您保存的文檔剛剛生效。 因為新的請求可能會覆蓋潛在客戶中的對象。 您需要在請求范圍內執行此邏輯。 一個請求的一個范圍。 並非一無所有。

您最初設置var document = {} ,而{}並非虛假。 最好將其設置為起始值document = null ,然后在檢查!document set document = {}之后,再分配所需的任何屬性。

您需要閱讀Javascript中的面向對象編程

您在代碼頂部附近定義的匿名函數構造函數,因此對於您希望當前未初始化的document屬性,只需鍵入以下內容:

this.document = null;

然后一段時間后,當您使用此構造函數創建新對象時,如下所示:

var myLead = new Lead(dbConnection);

您將擁有myLead.document屬性。

但是,您的代碼還有很多其他問題。 為什么要假設在定義為{}時在庫中存在一個具有相關數據的全局document變量? 當在下面的其他文件中設置document屬性時,應在構造函數末尾的if語句中運行代碼,並且應僅希望this.document存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM