Async.mjs在直接调用时有效,在从另一个.mjs调用时失败



我目前正在使用Ring-Client-API,在开发的最后遇到了一个小问题。我成功地创建、测试并运行了我的RingListener作为一个单独的文件,即通过执行RingListener.js。我的目标是现在从另一个文件位置启动侦听器,在尝试这样做时遇到了一些问题。我更熟悉CommonJS,所以请随时为我指出我缺少的ES6内容的正确方向。我正在运行节点14.15.4

CodeRingListener.js:

import {RingApi} from 'ring-client-api'
import * as dotenv from "dotenv";
dotenv.config({path: '../.env'});
import {readFile, writeFile} from 'fs'
import {promisify} from 'util'
import App from "../objects/GoogleHomeNotification.js";
export async function start() {
const {env} = process;
console.log("Test 1")
const ringApi = new RingApi({my credentials});
console.log("Test 2")
const allCameras = await ringApi.getCameras();
console.log("Test 3")
console.log("Found " + allCameras.length + " camera(s)")
ringApi.onRefreshTokenUpdated.subscribe(
async ({newRefreshToken, oldRefreshToken}) => {
console.log('Refresh Token Updated: ', newRefreshToken)
}
)
if (allCameras.length) {
console.log('Listening for motion and doorbell presses on your cameras.')
}
}
start();

RingListener.js 的输出

Test 1
Test 2
Test 3
Found 1 camera(s).
Refresh Token Updated: {my token}
Now writing it to proper .env file
Listening for motion and doorbell presses on your cameras.

当我尝试从另一个文件启动它时,我只进入了测试2。开始.mjs

import {start} from './objects/RingListener.mjs'
start();
//await start(); //Returns the same results as just start()

Start.mjs 的输出

Test 1
Test 2

当从另一个位置运行它时,它似乎被第一个等待语句卡住了,我不知道为什么。如有任何帮助,我们将不胜感激。我很困惑,因为我能够实际执行该函数,并且我得到了控制台日志语句,但由于某种原因,当通过另一个文件执行时,它总是在与等待调用完全相同的位置失败。从另一个文件调用异步函数时,是否缺少某些内容?

谢谢!

编辑:感谢@JoshA为我指明了dotenv文件路径的正确方向。

下面的代码现在挂在";测试1测试2";当我尝试导入另一个js模块时。

import {start} from './objects/RingListener.mjs'
import {default as Webserver} from './app.js' 
await start();

输出

Test 1 
Test 2

但当我删除对另一个类的导入时,它运行得很好,IE";测试1、2、3等;。

import {start} from './objects/RingListener.mjs'
//import {default as Webserver} from './app.js'
await start();

输出

Test 1 
Test 2
Test 3
Found 1 camera(s).
Refresh Token Updated:  
Now writing it to proper .env file
Listening for motion and doorbell presses on your cameras.

我甚至还没有使用它,它仍然导致它挂起。最终我将使用Webserver.listen((;但是/apps只是导出express应用程序。

编辑:应用程序.js包含一堆变量初始化和快速应用程序配置。映射到服务器上的不同路由。目标是删除app.js中的app.listen((,并将其移动到Start.js中,然后通过导入中的Webserver.listen((调用它。

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var logger = require('morgan');
require('dotenv').config()
/* Variable def here */
var app = express();
// app config here
/*  Exports  */
module.exports = app;
app.listen(1337, () => {
console.log("Starting server on 1337");
})

我假设您正在使用dotenv.env文件加载凭据,然后将其传递给new RingApi({my credentials})构造函数。

如果是这样的话,它失败的最可能原因是dotenv使用fs.readFileSync读取.env文件,该文件查找与执行节点js的路径相关的文件,而不是与模块的路径相关。这就是为什么如果你从不同路径的Start.mjs执行应用程序,它就会停止工作。

如果您真的想在RingListener.mjs文件中保留dotenv-config调用,您可以将其重写为类似这样的内容,解析.env文件的绝对路径。

import { resolve } from 'path';
dotenv.config({path: resolve(__dirname, '../.env')});

如果您得到一个错误__dirname is not defined,这是因为它在ECMAScript模块中不可用,如本文所述。

作为一种变通方法,你可以做这样的事情。

import { fileURLToPath } from 'url';
import { dirname, resolve } from 'path';
// Initialize __dirname
const __dirname = dirname(fileURLToPath(import.meta.url));
// Then use it to resolve path for .env
dotenv.config({path: resolve(__dirname, '../.env')});

最新更新