Promise.all in Node.js 不调用 then 函数
Promise.all in Node.js doesn't call the then function
我学习了如何使用 Node 和 Ecmascript 6。
我的脚本的目的是重命名目录中的 png 文件列表。我只想重命名 png 文件(假设也有 jpg)并在最后显示重命名的文件数。由于 Node 的非阻塞特性,它不是那么明显,我决定利用这个机会来发现 ES6 承诺。
'use strict';
const fs = require('fs-extra');
const dir = '/Users/toto/Desktop/png/';
const suffix = '_IMAGE.';
const regex = /(.*)\.(png)$/;
var nbFiles = 0;
// Rename a png file with a suffix
var renameFile = (filename) => {
return new Promise((resolve, reject) => {
if(regex.test(filename)){
let newFileName = filename.replace(regex, '' + suffix + '');
fs.rename(dir + filename, dir + newFileName, (err) => {
let msg = filename + ' => ' + newFileName;
if (err) {
console.log('KO : rename of ' + msg);
reject(err);
}
console.log('OK : rename of ' + msg);
resolve(nbFiles++);
});
}
});
};
// Read files in a directory and call renameFile + display number of files renamed
fs.readdir(dir, (err, files) => {
if(err) return console.error(err);
var promise = Promise.all(
files.map(renameFile)
).then(function(nb){
console.log('Number of files renamed : ', nb);
}).catch(function(err){
console.log('Error ', err);
});
});
预期结果是重命名文件并看到消息重命名的文件数。
我得到重命名的文件,但我看不到任何消息(then 或 catch 调用)。某处出了点问题,但调试会话帮不了我。
感谢您的帮助!
PS :我的环境是 Node 5.10 和 OS X 10.11。
问题是您正在创建一些永远悬而未决(永远不会解决)的承诺:当 regex
与 filename
不匹配时。 Promise.all
会无限期地等待他们。
你应该总是 promisify 在尽可能低的级别 - 在你的情况下 fs.rename
和 fs.readdir
- 并且没有在处理 [=26= 的函数中放置其他代码]回调API。没有应用程序逻辑,没有字符串连接,没有日志记录,什么都没有。
function rename(from, to) {
return new Promise((resolve, reject) => {
fs.rename(from, to, (err, res) => {
if (err) reject(err);
else resolve(res);
});
});
}
function readdir(from, to) {
return new Promise((resolve, reject) => {
fs.readdir(from, to, (err, res) => {
if (err) reject(err);
else resolve(res);
});
});
}
(如果这看起来是重复的 - 它是 - 编写一个辅助函数,或者使用 promise 库中的一个)
有了这些,您现在可以正确(并且更容易)实现您的脚本:
const dir = '/Users/toto/Desktop/png/';
const suffix = '_IMAGE.';
const regex = /(.*)\.(png)$/;
readdir(dir).then(files =>
Promise.all(files.map(filename => ({
from: dir + filename,
to: dir + filename.replace(regex, '' + suffix + '')
})).filter(r => r.from != r.to).map(r => {
let msg = r.from + " => " + r.to;
return rename(r.from, r.to).then(() => {
console.log("OK: " + msg);
}, err => {
console.log("KO: " + msg);
throw err;
});
}));
).then(function(res) {
console.log('Number of files renamed : ', res.length);
}).catch(function(err) {
console.error('Error ', err);
});
我学习了如何使用 Node 和 Ecmascript 6。
我的脚本的目的是重命名目录中的 png 文件列表。我只想重命名 png 文件(假设也有 jpg)并在最后显示重命名的文件数。由于 Node 的非阻塞特性,它不是那么明显,我决定利用这个机会来发现 ES6 承诺。
'use strict';
const fs = require('fs-extra');
const dir = '/Users/toto/Desktop/png/';
const suffix = '_IMAGE.';
const regex = /(.*)\.(png)$/;
var nbFiles = 0;
// Rename a png file with a suffix
var renameFile = (filename) => {
return new Promise((resolve, reject) => {
if(regex.test(filename)){
let newFileName = filename.replace(regex, '' + suffix + '');
fs.rename(dir + filename, dir + newFileName, (err) => {
let msg = filename + ' => ' + newFileName;
if (err) {
console.log('KO : rename of ' + msg);
reject(err);
}
console.log('OK : rename of ' + msg);
resolve(nbFiles++);
});
}
});
};
// Read files in a directory and call renameFile + display number of files renamed
fs.readdir(dir, (err, files) => {
if(err) return console.error(err);
var promise = Promise.all(
files.map(renameFile)
).then(function(nb){
console.log('Number of files renamed : ', nb);
}).catch(function(err){
console.log('Error ', err);
});
});
预期结果是重命名文件并看到消息重命名的文件数。
我得到重命名的文件,但我看不到任何消息(then 或 catch 调用)。某处出了点问题,但调试会话帮不了我。
感谢您的帮助!
PS :我的环境是 Node 5.10 和 OS X 10.11。
问题是您正在创建一些永远悬而未决(永远不会解决)的承诺:当 regex
与 filename
不匹配时。 Promise.all
会无限期地等待他们。
你应该总是 promisify 在尽可能低的级别 - 在你的情况下 fs.rename
和 fs.readdir
- 并且没有在处理 [=26= 的函数中放置其他代码]回调API。没有应用程序逻辑,没有字符串连接,没有日志记录,什么都没有。
function rename(from, to) {
return new Promise((resolve, reject) => {
fs.rename(from, to, (err, res) => {
if (err) reject(err);
else resolve(res);
});
});
}
function readdir(from, to) {
return new Promise((resolve, reject) => {
fs.readdir(from, to, (err, res) => {
if (err) reject(err);
else resolve(res);
});
});
}
(如果这看起来是重复的 - 它是 - 编写一个辅助函数,或者使用 promise 库中的一个)
有了这些,您现在可以正确(并且更容易)实现您的脚本:
const dir = '/Users/toto/Desktop/png/';
const suffix = '_IMAGE.';
const regex = /(.*)\.(png)$/;
readdir(dir).then(files =>
Promise.all(files.map(filename => ({
from: dir + filename,
to: dir + filename.replace(regex, '' + suffix + '')
})).filter(r => r.from != r.to).map(r => {
let msg = r.from + " => " + r.to;
return rename(r.from, r.to).then(() => {
console.log("OK: " + msg);
}, err => {
console.log("KO: " + msg);
throw err;
});
}));
).then(function(res) {
console.log('Number of files renamed : ', res.length);
}).catch(function(err) {
console.error('Error ', err);
});