在节点模块中承诺使用

Promise usage inside node module

我是 promise 主题的新手,我想知道我是否编写了以下代码 应该如此。

我们正在我们的项目中使用bluebird

这是代码:

var start = function (destination ){
    return new Promise(function (resolve, reject) {
        fs.readdir(destination, function (err, values) {
            if (err) {
                reject(err);
            } else {
                values.reverse();
                var flag = true;
                values.forEach(function (file) {
                    if (flag) {
                        flag = false;
                        resolve();
                    } else {
                        fs.unlink(destination + '/' + file, function (err) {
                            if (err) {
                                console.log('Error ' + err);
                                reject(err);
                            } else {
                                console.log('sucess ' + dest + '/' + file);
                                resolve();
                            }
                        });
                    }
                });
            }
        });

    });
};

在 bluebird 中,使用 new Promise 是一种反模式,应尽可能避免使用。相反,您可以使用 bluebird 的 promisifyAll() method to promisify fs 并将其作为起点。

例如:

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));

var start = function (destination ) {
    return fs.readdirAsync(destination)
        .then(values => values.reverse()) // or `.call("reverse")`
        .then(values => {
            // your logic
        }); // .catch(err => { ... }); // by default bluebird logs errors to the console
};

在您进一步的逻辑中,您试图多次履行或拒绝承诺,这是不可能的 - 这里只会考虑对 resolve/reject 的第一次调用。我想你想删除除最新文件以外的所有文件。所以像

var start = function (destination ) {
    return fs.readdirAsync(destination)
        .then(values => values.reverse())
        .then(files => {
            files.shift();
            return files;
        })
        .map(file => fs.unlinkAsync(`${destination}/${file}`))
        .then(success => {
            console.log(success) // will hold an array of success messages
            return success;
        });
};

会做你想做的,喜欢它应该做的。


如果您使用的节点早于 v4 或者不熟悉 es6,这里是 es5 版本:

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));

var start = function start(destination) {
    return fs.readdirAsync(destination).then(function (values) {
        return values.reverse();
    }).then(function (files) {
        files.shift();
        return files;
    }).map(function (file) {
        return fs.unlinkAsync(destination + '/' + file);
    }).catch(function (err) {
        console.log(err);
    });
};

别急,老虎,你的工作比你需要的要努力得多。

你的逻辑是:

  1. 读取目标中的所有文件
  2. 反转它们
  3. 保存最后一个文件,不要取消链接。
  4. 取消所有其他文件的链接

这是使用 coroutines 和 bluebird 的替代答案:

let Promise = require("bluebird");
let fs = require("fs");
Promise.promisifyAll("fs");

const start = Promise.coroutine(function* (destination) { 
    let files = yield fs.readdirAsync(destination); // 1. read files
    files = files.reverse(); 2. reverse them
    files.shift(); // 3. except the first one
    yield Promise.map(files, f => fs.unlinkAsync(`${destination}/${f}`)); 4. unlink
});

或者,可能更优雅:

const start = Promise.coroutine(function* (destination) { 
    let files = yield fs.readdirAsync(destination);
    files.pop();
    yield Promise.map(files, f => fs.unlinkAsync(`${destination}/${f}`));
});