Nodejs中在对象的第二个方法调用第一个对象的方法时,第一个方法没有定义?

Nodejs中在对象的第二个方法调用第一个对象的方法时,第一个方法没有定义?

在Test里面有两个方法,getInfo 与pushSeller,当我在pushSeller中调用getInfo时是为定义错误。请问是作用域得问题吗?谢谢!

function Test() {

  this.style = new Xinge.Style(4, 1, 1, 1, 0);

  this.getInfo = function (os, flag) {
    this.accessId = Number(process.env['XINGE_' + flag +'_' + os + '_ACCESS_ID']);
    this.secretKey = process.env['XINGE_' + flag + '_' + os + '_SECRET_KEY'];
    this.XingeApp = new Xinge.XingeApp(this.accessId, this.secretKey);
  }
  this.pushSeller = function (seller_id, title, content) {
    console.log(this.getInfo); //在这我可用访问到getInfo
    db.query(
      "SELECT * FROM seller_admin WHERE seller_id=?", [seller_id],
      function (err, seller_admin) {
        if (err) {
          return console.log(err);
        }
        
        if (seller_admin.length) {
          for (var i = 0; i < seller_admin.length; i++) {
            (function (i) {
              db.query(
                "SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
                function (err, user) {
                  if (err) {
                    return console.log(err);
                  }
                  if (user[0].pushtoken) {
                    if (user[0].os == 'android') {
                      console.log(user);
                      this.getInfo('ANDROID', 'SHOP'); //在这里我访问不到getInfo
                      this.android(user[0].pushtoken, title, content)
                    }
                  }
                }

              );
            })(i);
          }
        }
      }
    );
  }
}

5 回复

在Node.js中,当你在一个回调函数内部使用this关键字时,它可能不会指向你期望的对象实例。这是因为JavaScript中的this关键字会根据函数的调用上下文来改变其值。在你的例子中,在db.query的回调函数内部,this不再指向Test对象,而是指向全局对象(在浏览器环境中通常是window,而在Node.js环境中通常是global)。

示例代码及解释

function Test() {
  this.style = new Xinge.Style(4, 1, 1, 1, 0);

  this.getInfo = function (os, flag) {
    this.accessId = Number(process.env['XINGE_' + flag +'_' + os + '_ACCESS_ID']);
    this.secretKey = process.env['XINGE_' + flag + '_' + os + '_SECRET_KEY'];
    this.XingeApp = new Xinge.XingeApp(this.accessId, this.secretKey);
  }

  this.pushSeller = function (seller_id, title, content) {
    console.log(this.getInfo); // 在这里可访问到getInfo

    db.query(
      "SELECT * FROM seller_admin WHERE seller_id=?", [seller_id],
      function (err, seller_admin) {
        if (err) {
          return console.log(err);
        }
        
        if (seller_admin.length) {
          for (var i = 0; i < seller_admin.length; i++) {
            (function (i) {
              db.query(
                "SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
                function (err, user) {
                  if (err) {
                    return console.log(err);
                  }
                  if (user[0].pushtoken) {
                    if (user[0].os == 'android') {
                      console.log(user);
                      // 使用箭头函数来保持正确的this上下文
                      const getInfo = () => this.getInfo('ANDROID', 'SHOP');
                      getInfo();
                      this.android(user[0].pushtoken, title, content);
                    }
                  }
                }
              );
            })(i);
          }
        }
      }
    );
  }
}

解释

  1. 箭头函数:在JavaScript中,箭头函数不会创建自己的this上下文,而是继承自父作用域。因此,我们使用箭头函数来确保this指向Test对象实例。

  2. 保存this引用:另一种常见的方式是先保存this引用到一个变量(如self),然后在回调函数中使用该变量。例如:

    var self = this;
    db.query("SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
      function (err, user) {
        if (err) {
          return console.log(err);
        }
        if (user[0].pushtoken) {
          if (user[0].os == 'android') {
            console.log(user);
            self.getInfo('ANDROID', 'SHOP');
            self.android(user[0].pushtoken, title, content);
          }
        }
      }
    );
    

通过上述方式,你可以确保在异步回调函数中正确地访问到Test对象的方法。


进回调了,肯定拿不到。 db.query() 明显进回调了。 //混合(MIX)方法到SESSION或者GLOBAL。是最佳解决方法。

this指向当前函数.你看看你用this时,this指向谁?

gloabal.path = this;在上面声明,下面用global.path代替this.

在你提供的代码中,this 的上下文在回调函数内部发生了变化,导致 this.getInfo 无法正确访问。可以通过使用箭头函数或保存外部的 this 来解决这个问题。

示例代码

function Test() {
  this.style = new Xinge.Style(4, 1, 1, 1, 0);

  this.getInfo = function (os, flag) {
    this.accessId = Number(process.env['XINGE_' + flag +'_' + os + '_ACCESS_ID']);
    this.secretKey = process.env['XINGE_' + flag + '_' + os + '_SECRET_KEY'];
    this.XingeApp = new Xinge.XingeApp(this.accessId, this.secretKey);
  };

  this.pushSeller = function (seller_id, title, content) {
    db.query(
      "SELECT * FROM seller_admin WHERE seller_id=?", [seller_id],
      (err, seller_admin) => {
        if (err) {
          return console.log(err);
        }

        if (seller_admin.length) {
          for (let i = 0; i < seller_admin.length; i++) {
            (function (i) {
              db.query(
                "SELECT os, pushtoken FROM user WHERE uid =?", [seller_admin[i].uid],
                (err, user) => {
                  if (err) {
                    return console.log(err);
                  }
                  if (user[0] && user[0].pushtoken) {
                    if (user[0].os === 'android') {
                      console.log(user);
                      this.getInfo('ANDROID', 'SHOP');
                      this.android(user[0].pushtoken, title, content);
                    }
                  }
                }
              );
            })(i);
          }
        }
      }
    );
  };
}

const testInstance = new Test();

解释

  1. 使用箭头函数:在 db.query 的回调函数中使用箭头函数,可以保持正确的 this 上下文。
  2. 保存外部的 this:可以在函数外部保存一个引用,例如 self = this,然后在回调函数内部使用 self.getInfo

其他注意事项

  • 确保在 db.query 的回调函数内部正确处理 this 的上下文。
  • 检查 process.env 中的环境变量是否已正确设置。
  • 确保 Xingedb 相关模块已正确导入。

通过这些修改,你应该能够成功调用 getInfo 方法。

回到顶部