谢谢各位,问题已解决,可以看3楼,说的很清楚。
在使用fs包一层promise后,使用async await执行,导致顺序错乱,log也不打,只会执行一次fs方法,下面是输出和代码
D:\code\mygitali\nodestudy>node index.js
开始创建文件夹
D:\code\mygitali\nodestudy>node index.js
开始删除文件夹
D:\code\mygitali\nodestudy>node index.js
开始创建文件夹
D:\code\mygitali\nodestudy>node index.js
开始删除文件夹
await-fs.js
const fs = require('fs');
const ab = ['access', 'rename', 'ftruncate', 'chown', 'lchown', 'cmod', 'fchmod', 'stat', 'lstat', 'fstat', 'link', 'symlink',
'readlink', 'realpath', 'unlink', 'rmdir', 'readdir', 'close', 'open', 'utimes',
'futimes', 'fsync', 'write', 'read', 'readFile', 'writeFile', 'appendFile', 'mkdir', 'mkdtemp']
// fchown fdatasync mkdtemp rename truncate
ab.forEach(name => {
if (!fs[name])return;
exports[name] = (...n) => {
return new Promise((res, rej) => {
fs[name](...n, (er, d) => {
if (er) rej(er)
if (d) res(d)
})
})
}
})
exports.exists = (path) => {
return new Promise((res, rej) => {
fs.exists(path, (exists) => {
res(exists);
})
});
}
index.js
const fs = require('./await-fs');
const run = async () => {
try {
let path = './lib';
// 判断有没有lib文件夹
let exists = await fs.exists(path);
if (exists) {
console.log('开始删除文件夹')
// 删除文件夹
let re1s =await fs.rmdir(path);
console.log('删除文件夹完成',re1s)
}
console.log('开始创建文件夹')
// 创建文件夹
let res = await fs.mkdir('./lib');
console.log('创建文件夹完成', res)
console.log('开始创建文件')
await fs.writeFile('./lib/1.txt', '大哥', 'utf8');
console.log('创建文件夹完成')
}
catch (err) {
console.log(err)
}
}
run()
单独执行以下你用promise包装的fs函数是否正确。 另外如果用bluebird的话直接用promisifyAll就好了吧,不用这样一个一个包装
问题在这个位置
return new Promise((res, rej) => {
fs[name](...n, (er, d) => {
if (er) rej(er)
if (d) res(d)
})
})
看一看fs的API文档,你会发现callback里只会有err一个参数,不是像其他函数一样在操作成功时有其他参数,也就是说永远不会有d这个参数 所以这个promise永远不会resolve,而执行到这里node的事件循环中就没有任务了,所以程序终止 (而不是因为没有resolve一直处于await状态!) 可以改成
return new Promise((res, rej) => {
fs[name](...n, (er) => {
if (er) rej(er)
else res(true)
})
})
关于更简单的方法 可以参阅 util.promisify
封装具体细节可以参考这篇文章http://welefen.com/post/how-to-convert-callback-to-promise.html
@dislido 正解,回调中只有error一个参数,是我不细心了,谢谢。
const fs = require('fs');
const ab = ['access', 'rename', 'ftruncate', 'chown', 'lchown', 'cmod', 'fchmod', 'stat', 'lstat', 'fstat', 'link', 'symlink',
'readlink', 'realpath', 'unlink', 'rmdir', 'readdir', 'close', 'open', 'utimes',
'futimes', 'fsync', 'write', 'read', 'readFile', 'writeFile', 'appendFile', 'mkdir', 'mkdtemp']
// fchown fdatasync mkdtemp rename truncate
ab.forEach(name => {
if (!fs[name])return;
exports[name] = function() {
var params=Array.prototype.slice.call(arguments);
return new Promise((res, rej) => {
params.push((err, d) => {
if (err) return rej(err);
res(d||true);
});
fs[name].apply(fs,params);
})
}
})
exports.exists = (path) => {
return new Promise((res, rej) => {
fs.exists(path, (exists) => {
res(exists);
})
});
}
@dislido 这里是指mkdir
函数吧?
@tangdaohai 是的,还有rmdir,fs里很多函数的回调都是只有一个err的
@dislido 看了你的解释发现我之前的理解有些错误,确实是因为有些fs接口没有resolve的问题,但对于会面“事件循环中没有执行任务了,所以程序终止”这个解释有些疑问,我认为是await后面的promise没有reslove调用,导致程序运行机制没有切回宏队列,不能运行后面的语句,导致程序终止