You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

引入外部JavaScript文件函数时触发TypeError:不是函数

解决TypeError及异步逻辑问题

嘿,我来帮你搞定这个问题!你现在遇到的TypeError: verifyNoExistingUser is not a function,核心原因是导出和引入的方式不匹配,另外还有个隐藏的异步逻辑问题——就算你解决了TypeError,原来的代码也没法正确判断用户是否存在,因为异步操作的结果不能用同步return获取,我一起给你修复:

第一步:修复导出/引入不匹配的问题

你的UsersController.js导出的是一个构造函数,但你在app.js里直接尝试调用构造函数上的verifyNoExistingUser方法,这当然找不到啦。有两种简单的修复方式:

方式1:直接导出包含方法的对象(推荐)

修改UsersController.js,把构造函数改成直接导出方法对象,这样不用实例化就能调用:

var User = require('../user/User'); 

// 直接导出包含方法的对象
module.exports = {
  // 加入回调函数处理异步结果
  verifyNoExistingUser: function(email, name, callback) {
    // 先检查邮箱是否存在
    User.findOne({email: email}, function(err, user){
      if(err){
        return callback(err); // 把错误传递给回调
      }
      if(user){
        // 邮箱已存在,返回false
        return callback(null, false);
      }
      // 邮箱不存在,继续检查用户名
      User.findOne({name: name}, function(err, user){
        if(err){
          return callback(err);
        }
        // 用户名不存在返回true,存在返回false
        callback(null, !user);
      });
    });
  }
};

方式2:保持构造函数,引入时实例化

如果你想保留原来的构造函数写法,就在app.js里先实例化再调用:

var UsersController = require('../user/UsersController.js');
var usersController = new UsersController(); // 实例化控制器

后续调用时用usersController.verifyNoExistingUser(...)即可。

第二步:修复异步逻辑的问题

原来的代码里,User.findOne是异步操作,你直接return true/false根本拿不到正确结果——因为异步代码还没执行完,外层的if判断已经跑完了。所以必须用回调、Promise或async/await处理异步结果:

用回调的方式调用(对应方式1的导出)

修改app.js中的注册接口,改用回调接收验证结果:

var express = require('express');
var router = express.Router();
...
var UsersController = require('../user/UsersController.js');
...
router.post('/register', function(req, res){
  var hashedPassword = bcrypt.hashSync(req.body.password, 8);
  
  // 调用验证方法,通过回调获取结果
  UsersController.verifyNoExistingUser(req.body.email, req.body.name, function(err, isAvailable) {
    if(err){
      return res.status(500).send('Error on the server.');
    }
    if(!isAvailable){
      return res.status(400).send("Username or email already exists.");
    }
    // 验证通过,继续执行注册逻辑(比如创建新用户)
    // ... 这里写你的用户创建代码
  });
});

更现代的async/await写法(推荐)

如果你的项目支持ES6+,可以把验证方法改成返回Promise,然后用async/await简化代码:

修改UsersController.js:

var User = require('../user/User'); 

module.exports = {
  verifyNoExistingUser: async function(email, name) {
    try {
      // 检查邮箱
      const emailUser = await User.findOne({email: email});
      if(emailUser) return false;
      
      // 检查用户名
      const nameUser = await User.findOne({name: name});
      return !nameUser;
    } catch(err) {
      throw new Error('Error on the server.');
    }
  }
};

然后修改app.js的注册接口:

router.post('/register', async function(req, res){
  try {
    var hashedPassword = bcrypt.hashSync(req.body.password, 8);
    
    // 用await等待异步验证结果
    const isAvailable = await UsersController.verifyNoExistingUser(req.body.email, req.body.name);
    if(!isAvailable){
      return res.status(400).send("Username or email already exists.");
    }
    // 验证通过,继续注册流程
    // ...
  } catch(err) {
    return res.status(500).send(err.message);
  }
});

这样既解决了TypeError的问题,又能正确处理异步的数据库查询,保证功能正常运行~

内容的提问来源于stack exchange,提问作者Carson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:03:31