Node.js中的Promise.all没有't调用then函数

Promise.all in Node.js doesn't call the then function

本文关键字:调用 then 函数 中的 js Promise all 没有 Node      更新时间:2023-10-22

我学习了如何使用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, '$1' + suffix + '$2');
        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);
    });
});

预期的结果是重命名文件,并看到消息Number of files renamed。

我重命名了文件,但我看不到任何消息(关于then或catch调用)。有些地方出了问题,但调试会话对我没有帮助。

谢谢你的帮助!

PS:我的环境是Node 5.10和OS X 10.11。

问题是,当regexfilename不匹配时,您正在创建一些永远挂起(永远无法解决)的承诺。Promise.all将无限期地等待他们。

您应该始终在尽可能低的级别上promisify——在您的情况下是fs.renamefs.readdir——并且在处理"旧"回调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, '$1' + suffix + '$2')
    })).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);
});