无法读取 node.js 中未定义的属性“then”?

Posted

技术标签:

【中文标题】无法读取 node.js 中未定义的属性“then”?【英文标题】:can not read property 'then' of undefined in node.js? 【发布时间】:2020-04-17 04:50:36 【问题描述】:

在 models/index.js 文件中,我正在尝试编写数据库连接

const connectDb = () => 
  if (process.env.TEST_DATABASE_URL) 
    return mongoose.connect(
      process.env.TEST_DATABASE_URL,
       useNewUrlParser: true ,
    );
  

  if (process.env.DATABASE_URL) 
    return mongoose.connect(
      process.env.DATABASE_URL,
       useNewUrlParser: true ,
    );
  
;

在主 index.js 文件中,我尝试调用 connectDb() 函数,如下所示:-

connectDb().then(async () => 
  if (isTest || isProduction) 
    // reset database
    await Promise.all([
      models.User.deleteMany(),
      models.Message.deleteMany(),
    ]);

    createUsersWithMessages(new Date());
  

  httpServer.listen( port , () => 
    console.log(`Apollo Server on http://localhost:$port/graphql`);
  );
);

我收到如下错误:-

TypeError: Cannot read property 'then' of undefined
    at Object.<anonymous> (D:\Gaurav's-Stuff\fullstack-apollo-express-mongodb-boilerplate\src/index.js:95:1)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Module._compile (D:\Gaurav's-Stuff\fullstack-apollo-express-mongodb-boilerplate\node_modules\pirates\lib\index.js:83:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Object.newLoader [as .js] (D:\Gaurav's-Stuff\fullstack-apollo-express-mongodb-boilerplate\node_modules\pirates\lib\index.js:88:7)        
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at Object.<anonymous> (D:\Gaurav's-Stuff\fullstack-apollo-express-mongodb-boilerplate\node_modules\@babel\node\lib\_babel-node.js:224:23)   
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)```

【问题讨论】:

你的 const connectDb = () =&gt; 不是异步的,也没有返回任何承诺,你必须在 connectDb 函数中解决它,.then 抓住了承诺,因此你得到了错误 @Coderboi,我无法理解,我该怎么做,你能举个例子吗?? 您使用的是哪个版本的猫鼬? @Coderboi 我使用的是猫鼬版本:- "^5.8.3" 检查您的 process.env.TEST_DATABASE_URL 和 process.env.DATABASE_URL 【参考方案1】:

这应该可以工作

const connectDb = async () => 
  let x = null;
  if (process.env.TEST_DATABASE_URL) 
    x = await mongoose.connect(
      process.env.TEST_DATABASE_URL,
       useNewUrlParser: true ,
    );
  

  if (process.env.DATABASE_URL) 
    x = await mongoose.connect(
      process.env.DATABASE_URL,
       useNewUrlParser: true ,
    );
  
  if(x) return Promise.resolve(db)  else  return Promise.reject("reject"); 

;

【讨论】:

解决了什么问题?如果mongoose.connect() 返回一个promise(您似乎认为它确实如此,因为您正在使用await),那么OP 的代码同样可以正常工作,因为OP 已经返回了它。如果 if 语句中的任何一个都没有计算为 true,那么 OP 的代码和您的代码都会出现问题。 stackblitz.com/edit/js-yxe3f6?embed=1&view=editorconnectDb () 没有异步标签就无法工作,.then(() =&gt; ()) 需要异步功能,我让他知道发生了什么,所以我没有直接返回 .connect @jfriend00 你的意见是什么 这只是添加了额外的代码,没有做任何有用的事情。真正的错误是您的if (x) 中没有else,或者如果在OP 的代码中if 都为false,则没有案例处理。考虑你自己的代码:if (x) return a promise // else return undefined【参考方案2】:

如果您收到此错误:

TypeError: Cannot read property 'then' of undefined

从这行代码:

connectDb().then(async () => 

那么,这意味着 connectDb() 正在返回 undefined 而不是返回承诺。

查看该代码:

const connectDb = () => 
  if (process.env.TEST_DATABASE_URL) 
    return mongoose.connect(
      process.env.TEST_DATABASE_URL,
       useNewUrlParser: true ,
    );
  

  if (process.env.DATABASE_URL) 
    return mongoose.connect(
      process.env.DATABASE_URL,
       useNewUrlParser: true ,
    );
  
;

我们知道,在你所说的 mongoose 版本中,mongoose.connect() 已经返回了一个承诺,所以connectDb() 不能返回一个承诺的唯一方法是,如果你的两个 if 语句都被评估为假,如果两者都没有process.env.TEST_DATABASE_URLprocess.env.DATABASE_URL 有一个值,或者 mongoose.connect() 实际上没有返回一个承诺(你不知何故安装了旧版本的猫鼬)。

验证环境变量的一种简单方法是添加几个日志语句:

const connectDb = () => 
  if (process.env.TEST_DATABASE_URL) 
    console.log("Found TEST_DATABASE_URL");
    return mongoose.connect(
      process.env.TEST_DATABASE_URL,
       useNewUrlParser: true ,
    );
  

  if (process.env.DATABASE_URL) 
    console.log("Found DATABASE_URL");
    return mongoose.connect(
      process.env.DATABASE_URL,
       useNewUrlParser: true ,
    );
  

  console.log("Never supposed to get here")
  throw new Error("Need either TEST_DATABASE_URL OR DATABASE_URL set in the environment");
;

仅供参考,您的代码中有很多地方没有进行正确的错误检测或处理,从 db 连接开始,在您的第二个代码块中也是如此。

【讨论】:

以上是关于无法读取 node.js 中未定义的属性“then”?的主要内容,如果未能解决你的问题,请参考以下文章

未捕获的类型错误:无法读取 React ajax 调用中未定义的属性“then”?

如何修复'TypeError:无法读取 Javascript 中未定义的属性'标题'

Ionic5 agm/core:信息窗口 [isOpen] 错误:无法读取 agm-core.js 中未定义的属性“then”

TypeError:无法读取未定义的属性“获取”(Node.js)

Node.js + Discord.js:无法读取未定义的属性“类”

Node.js UnhandledPromiseRejection:TypeError:无法读取未定义的属性“符号”