不等待嵌套的承诺
Not awaiting nested promise
应该指出的是,我对所有这些异步内容都很陌生。
我试图等到文件的存在得到验证,如果需要,脚本会在更新文件之前创建文件。但是,我似乎不知道该怎么做。
我知道我可以使用 fs.writeFileSync
,但我更愿意让它异步,以保证它不会阻止任何用户 activity。
// this is now detectDriveInfo(), the entire function unedited, verbatim
async function detectDriveInfo(){
const exec = require('child_process').exec
let
totalFreespace = 0,
totalSize = 0,
drives = []
exec('wmic logicaldisk get freespace,name,size,volumename', (error, stdout)=>{
stdout
.trim()
.split('\r\r\n')
.map(value => value.trim().split(/\s{2,}/))
.slice(1)
.sort((a,b) => Number(a[0]) - Number(b[0]))
.forEach(async (value, i, a) => {
renderDriveInfo(...value)
totalFreespace += Number(value[0])
totalSize += Number(value[2])
drives.push([value[1], Number(value[2]) - Number(value[0])])
if (i === a.length-1) {
renderDriveInfo(totalFreespace,'ALL',totalSize,'')
updateConfigDrives(drives)
await guaranteeData(drives) // this and its nested promises have to happen/complete
updateData(drives) // before this
}
})
})
}
async function guaranteeData(drives){
const fs = require('fs')
if (!fs.existsSync('./data.json')) {
let json = {}
drives = drives.map(([v]) => v)
drives.forEach(v => {
json[v] = []
})
json = JSON.stringify(json, null, 2)
await fs.writeFile('./data.json', json, 'utf8', (error)=>{
if (error) throw error
console.log('The file, data.json, has been created.')
console.log(json)
})
return
}
}
控制台日志
1. should come last
2. The file, data.json, has been created.
3. {
"C:": [],
"G:": [],
"K:": [],
"D:": [],
"E:": [],
"H:": [],
"J:": [],
"I:": [],
"F:": []
}
我做错了什么?
你在混合回调和承诺。 fs.writeFile
returns undefined
的回调版本,不幸的是它是一个值 JavaScript 将非常乐意为你 await
(通过不等待任何东西全部)。
使用 fs Promises API 中的 fs.promises.writeFile
,无回调:
await fs.promises.writeFile('data.json', json, 'utf8')
console.log('The file, data.json, has been created.')
console.log(json)
你可能还想要 specify that the file should never be overwritten,以防它是在存在检查和写入之间创建的:
await fs.promises.writeFile('data.json', json, {
flag: 'wx',
encoding: 'utf8',
})
然后使用 fs.existsSync
的非同步等价物:
if (await fs.promises.access('data.json', fs.constants.F_OK)
.catch(err => err.code === 'ENOENT' || Promise.reject(err))) {
或者完全跳过存在检查并依赖 wx
如果创建 JSON 不是太昂贵。
forEach
和 async
动作总是错误的,因为 forEach
丢弃任何它的动作 returns,并且 return 的值异步功能至关重要。你需要一个定期循环到 运行 串行,虽然不清楚 drives
来自哪里:
for (const value of stdout) {
// ??
}
await guaranteeData(drives)
console.log('should come last')
// updateData(drives)
最后,detectDriveInfo()
需要 exec
的承诺版本才能正确解析。现在 promise it returns 也不会等待操作完成。
看到您的代码后,我建议改用现代 for … of
循环,其中 await 将按预期工作:
for (const value of stdout) {
// Inside this await will work as you aspecting
}
应该指出的是,我对所有这些异步内容都很陌生。
我试图等到文件的存在得到验证,如果需要,脚本会在更新文件之前创建文件。但是,我似乎不知道该怎么做。
我知道我可以使用 fs.writeFileSync
,但我更愿意让它异步,以保证它不会阻止任何用户 activity。
// this is now detectDriveInfo(), the entire function unedited, verbatim
async function detectDriveInfo(){
const exec = require('child_process').exec
let
totalFreespace = 0,
totalSize = 0,
drives = []
exec('wmic logicaldisk get freespace,name,size,volumename', (error, stdout)=>{
stdout
.trim()
.split('\r\r\n')
.map(value => value.trim().split(/\s{2,}/))
.slice(1)
.sort((a,b) => Number(a[0]) - Number(b[0]))
.forEach(async (value, i, a) => {
renderDriveInfo(...value)
totalFreespace += Number(value[0])
totalSize += Number(value[2])
drives.push([value[1], Number(value[2]) - Number(value[0])])
if (i === a.length-1) {
renderDriveInfo(totalFreespace,'ALL',totalSize,'')
updateConfigDrives(drives)
await guaranteeData(drives) // this and its nested promises have to happen/complete
updateData(drives) // before this
}
})
})
}
async function guaranteeData(drives){
const fs = require('fs')
if (!fs.existsSync('./data.json')) {
let json = {}
drives = drives.map(([v]) => v)
drives.forEach(v => {
json[v] = []
})
json = JSON.stringify(json, null, 2)
await fs.writeFile('./data.json', json, 'utf8', (error)=>{
if (error) throw error
console.log('The file, data.json, has been created.')
console.log(json)
})
return
}
}
控制台日志
1. should come last
2. The file, data.json, has been created.
3. {
"C:": [],
"G:": [],
"K:": [],
"D:": [],
"E:": [],
"H:": [],
"J:": [],
"I:": [],
"F:": []
}
我做错了什么?
你在混合回调和承诺。 fs.writeFile
returns undefined
的回调版本,不幸的是它是一个值 JavaScript 将非常乐意为你 await
(通过不等待任何东西全部)。
使用 fs Promises API 中的 fs.promises.writeFile
,无回调:
await fs.promises.writeFile('data.json', json, 'utf8')
console.log('The file, data.json, has been created.')
console.log(json)
你可能还想要 specify that the file should never be overwritten,以防它是在存在检查和写入之间创建的:
await fs.promises.writeFile('data.json', json, {
flag: 'wx',
encoding: 'utf8',
})
然后使用 fs.existsSync
的非同步等价物:
if (await fs.promises.access('data.json', fs.constants.F_OK)
.catch(err => err.code === 'ENOENT' || Promise.reject(err))) {
或者完全跳过存在检查并依赖 wx
如果创建 JSON 不是太昂贵。
forEach
和 async
动作总是错误的,因为 forEach
丢弃任何它的动作 returns,并且 return 的值异步功能至关重要。你需要一个定期循环到 运行 串行,虽然不清楚 drives
来自哪里:
for (const value of stdout) {
// ??
}
await guaranteeData(drives)
console.log('should come last')
// updateData(drives)
最后,detectDriveInfo()
需要 exec
的承诺版本才能正确解析。现在 promise it returns 也不会等待操作完成。
看到您的代码后,我建议改用现代 for … of
循环,其中 await 将按预期工作:
for (const value of stdout) {
// Inside this await will work as you aspecting
}