承诺在测试开始前得到解决
Promise being resolved before the beginning of test
解决方案
Converting the promises into the promise factory
修复了日志出现在测试 运行 之前的问题。我的 promise.all 没有解决,因为 I just assumed
NeDB 数据库初始化函数遵循回调模式而没有 properly going through the documentation
。再次查看文档后,我了解到它没有。从 promise 工厂中删除回调解决了这个问题。
问题
我有一个承诺链,其中 Promise
,如果解决,returns 和 Promise.all
。 Promise.all
接受了 3 个承诺。这是我的代码:
lib.init = (dir) => {
// check if the .data directory exists
return new Promise((resolve, reject) => {
if(dir) lib.baseDir = path.join(__dirname, '../', dir)
console.log('DATA LIBRARY INITIALIZATION: working directory - ', lib.baseDir)
fs.stat(lib.baseDir, (error, stats) => {
if(!error){
console.log('DATA LIBRARY INITIALIZATION: successfully retrieved file stats.')
if(!stats.isDirectory()) {
console.log('DATA LIBRARY INITIALIZATION: the base directory does not exist. Creating base directory now.')
fs.mkdir(lib.baseDir, (err) => {
if(!err) {
console.log('DATA LIBRARY INITIALIZATION: base directory created successfully.')
resolve()
} else reject('Could not create the data directory.')
})
} else resolve()
} else {
console.log('DATA LIBRARY INITIALIZATION: could not retrieve file stats. Creating base directory now.')
fs.mkdir(lib.baseDir, (err) => {
if(!err) {
console.log('DATA LIBRARY INITIALIZATION: base directory created successfully.')
resolve()
} else reject('Could not create the data directory.')
})
}
})
}).then(() => {
console.log('DATA LIBRARY INITIALIZATION: initializing databases.')
return Promise.all([loadComponents, loadShows, loadScreens])
})
}
以下是作为参数传递的 3 个承诺:
const loadShows = new Promise((resolve, reject) => {
// for saving profiles (set of screens designed/configured for different shows)
console.log('DATA LIBRARY INITIALIZATION: initializing SHOWS collection.')
lib.shows = new Datastore({ filename: path.join(lib.baseDir, 'shows.db'), autoload: true }, error => {
if(!error) {
console.log('DATA LIBRARY INITIALIZATION: successfully initialized SHOWS collection.')
resolve()
} else reject(`Could not load shows. Error: ${error.message}`)
})
})
const loadScreens = new Promise((resolve, reject) => {
// for saving screen settings (list of component settings)
console.log('DATA LIBRARY INITIALIZATION: initializing SCREENS collection.')
lib.screens = new Datastore({ filename: path.join(lib.baseDir, 'screens.db'), autoload: true }, error => {
if(!error) {
console.log('DATA LIBRARY INITIALIZATION: successfully initialized SCREENS collection.')
resolve()
} else reject(`Could not load screens. Error: ${error.message}`)
})
})
const loadComponents = new Promise((resolve, reject) => {
// for saving components (default settings for each component)
console.log('DATA LIBRARY INITIALIZATION: initializing COMPONENTS collection.')
lib.components = new Datastore({ filename: path.join(lib.baseDir, 'components.db'), autoload: true }, error => {
if(!error) {
console.log('DATA LIBRARY INITIALIZATION: successfully initialized COMPONENTS collection.')
resolve()
} else reject(`Could not load components. Error: ${error.message}`)
})
})
这是我的测试文件:
let chai = require('chai')
let chaiAsPromised = require('chai-as-promised')
chai.use(chaiAsPromised).should()
let _data = require('../lib/data')
describe('data library', () => {
describe('#init', () => {
it('should be able to initialize the collections without error', () => {
return _data.init('testData').should.be.fulfilled
})
})
after(function () {
// runs once after the last test in this block
// delete the testData directory and its contents
return _data.cleanup()
});
})
这是我在 运行 mocha
:
时得到的日志
yarn workspace v1.22.4
yarn run v1.22.4
$ mocha
DATA LIBRARY INITIALIZATION: initializing SHOWS collection.
DATA LIBRARY INITIALIZATION: initializing SCREENS collection.
DATA LIBRARY INITIALIZATION: initializing COMPONENTS collection.
data library
#init
DATA LIBRARY INITIALIZATION: working directory - /home/nm/projects/nightmoves/local-data/testData
DATA LIBRARY INITIALIZATION: could not retrieve file stats. Creating base directory now.
DATA LIBRARY INITIALIZATION: base directory created successfully.
DATA LIBRARY INITIALIZATION: initializing databases.
1) should be able to initialize the collections without error
DATA LIBRARY CLEANUP: removing everything in - /home/nm/projects/nightmoves/local-data/testData
DATA LIBRARY INITIALIZATION: cleanup successful.
0 passing (2s)
1 failing
1) data library
#init
should be able to initialize the collections without error:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/nm/projects/nightmoves/local-data/test/data.js)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
我不明白的是为什么我看到 promise.all 中通过的 Promises 的日志,甚至在测试 运行 by mocha 之前。
TLDR。
- Node.js 执行模块的所有语句 load/require.
- 承诺会立即执行,而不仅仅是当有人对他们的结果感兴趣时。
所以你的第二个片段是:
const loadShows = new Promise((resolve, reject) => {
}
const loadXXX = ...
只是创建这些承诺并在程序开始时立即执行(或者至少当模块是 require
d 或 import
-ed 时)。
然后执行 mocha 和其他代码并最终调用等待 Promise.all(...your promises)
的 init
,此时它们可能已经完成,因为它们完成得很快。
要解决此问题,请将您的功能更改为“承诺工厂”:
const loadShows = () => new Promise((resolve, reject) => {
}
const loadXXX = () => ...
然后像这样使用它们:
return Promise.all([loadShows(), ...])
或者将它们的声明移动到 init
方法中的 .then
处理程序。只有当你到达这段代码时,它们才会被实例化和执行。
解决方案
Converting the promises into the promise factory
修复了日志出现在测试 运行 之前的问题。我的 promise.all 没有解决,因为 I just assumed
NeDB 数据库初始化函数遵循回调模式而没有 properly going through the documentation
。再次查看文档后,我了解到它没有。从 promise 工厂中删除回调解决了这个问题。
问题
我有一个承诺链,其中 Promise
,如果解决,returns 和 Promise.all
。 Promise.all
接受了 3 个承诺。这是我的代码:
lib.init = (dir) => {
// check if the .data directory exists
return new Promise((resolve, reject) => {
if(dir) lib.baseDir = path.join(__dirname, '../', dir)
console.log('DATA LIBRARY INITIALIZATION: working directory - ', lib.baseDir)
fs.stat(lib.baseDir, (error, stats) => {
if(!error){
console.log('DATA LIBRARY INITIALIZATION: successfully retrieved file stats.')
if(!stats.isDirectory()) {
console.log('DATA LIBRARY INITIALIZATION: the base directory does not exist. Creating base directory now.')
fs.mkdir(lib.baseDir, (err) => {
if(!err) {
console.log('DATA LIBRARY INITIALIZATION: base directory created successfully.')
resolve()
} else reject('Could not create the data directory.')
})
} else resolve()
} else {
console.log('DATA LIBRARY INITIALIZATION: could not retrieve file stats. Creating base directory now.')
fs.mkdir(lib.baseDir, (err) => {
if(!err) {
console.log('DATA LIBRARY INITIALIZATION: base directory created successfully.')
resolve()
} else reject('Could not create the data directory.')
})
}
})
}).then(() => {
console.log('DATA LIBRARY INITIALIZATION: initializing databases.')
return Promise.all([loadComponents, loadShows, loadScreens])
})
}
以下是作为参数传递的 3 个承诺:
const loadShows = new Promise((resolve, reject) => {
// for saving profiles (set of screens designed/configured for different shows)
console.log('DATA LIBRARY INITIALIZATION: initializing SHOWS collection.')
lib.shows = new Datastore({ filename: path.join(lib.baseDir, 'shows.db'), autoload: true }, error => {
if(!error) {
console.log('DATA LIBRARY INITIALIZATION: successfully initialized SHOWS collection.')
resolve()
} else reject(`Could not load shows. Error: ${error.message}`)
})
})
const loadScreens = new Promise((resolve, reject) => {
// for saving screen settings (list of component settings)
console.log('DATA LIBRARY INITIALIZATION: initializing SCREENS collection.')
lib.screens = new Datastore({ filename: path.join(lib.baseDir, 'screens.db'), autoload: true }, error => {
if(!error) {
console.log('DATA LIBRARY INITIALIZATION: successfully initialized SCREENS collection.')
resolve()
} else reject(`Could not load screens. Error: ${error.message}`)
})
})
const loadComponents = new Promise((resolve, reject) => {
// for saving components (default settings for each component)
console.log('DATA LIBRARY INITIALIZATION: initializing COMPONENTS collection.')
lib.components = new Datastore({ filename: path.join(lib.baseDir, 'components.db'), autoload: true }, error => {
if(!error) {
console.log('DATA LIBRARY INITIALIZATION: successfully initialized COMPONENTS collection.')
resolve()
} else reject(`Could not load components. Error: ${error.message}`)
})
})
这是我的测试文件:
let chai = require('chai')
let chaiAsPromised = require('chai-as-promised')
chai.use(chaiAsPromised).should()
let _data = require('../lib/data')
describe('data library', () => {
describe('#init', () => {
it('should be able to initialize the collections without error', () => {
return _data.init('testData').should.be.fulfilled
})
})
after(function () {
// runs once after the last test in this block
// delete the testData directory and its contents
return _data.cleanup()
});
})
这是我在 运行 mocha
:
yarn workspace v1.22.4
yarn run v1.22.4
$ mocha
DATA LIBRARY INITIALIZATION: initializing SHOWS collection.
DATA LIBRARY INITIALIZATION: initializing SCREENS collection.
DATA LIBRARY INITIALIZATION: initializing COMPONENTS collection.
data library
#init
DATA LIBRARY INITIALIZATION: working directory - /home/nm/projects/nightmoves/local-data/testData
DATA LIBRARY INITIALIZATION: could not retrieve file stats. Creating base directory now.
DATA LIBRARY INITIALIZATION: base directory created successfully.
DATA LIBRARY INITIALIZATION: initializing databases.
1) should be able to initialize the collections without error
DATA LIBRARY CLEANUP: removing everything in - /home/nm/projects/nightmoves/local-data/testData
DATA LIBRARY INITIALIZATION: cleanup successful.
0 passing (2s)
1 failing
1) data library
#init
should be able to initialize the collections without error:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/nm/projects/nightmoves/local-data/test/data.js)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
我不明白的是为什么我看到 promise.all 中通过的 Promises 的日志,甚至在测试 运行 by mocha 之前。
TLDR。
- Node.js 执行模块的所有语句 load/require.
- 承诺会立即执行,而不仅仅是当有人对他们的结果感兴趣时。
所以你的第二个片段是:
const loadShows = new Promise((resolve, reject) => {
}
const loadXXX = ...
只是创建这些承诺并在程序开始时立即执行(或者至少当模块是 require
d 或 import
-ed 时)。
然后执行 mocha 和其他代码并最终调用等待 Promise.all(...your promises)
的 init
,此时它们可能已经完成,因为它们完成得很快。
要解决此问题,请将您的功能更改为“承诺工厂”:
const loadShows = () => new Promise((resolve, reject) => {
}
const loadXXX = () => ...
然后像这样使用它们:
return Promise.all([loadShows(), ...])
或者将它们的声明移动到 init
方法中的 .then
处理程序。只有当你到达这段代码时,它们才会被实例化和执行。