javascript - 使用回调 hell 将构建转换为 promise hell

标签 javascript node.js promise ecmascript-6 bluebird

我目前正在将带有一些回调 hell 的构建过程转换为 promise hell ( hell 很可能是因为我是 promises 的新手并且我对 Bluebird 缺乏经验)。我正在努力通过 .all 方法,但出现文件已存在的错误。也许其中的文件副本试图在开始时发生在 rimraf 之前?

const Promise    = require('bluebird');
const rcopyAsync = Promise.promisify(require('recursive-copy'));
const readAsync  = Promise.promisify(require('recursive-readdir'));
const rmrfAsync  = Promise.promisify(require('rimraf'));
const globAsync  = Promise.promisify(require('glob'));

rmrfAsync('{build,dist}')
    .then(() => {
        return readAsync('src');
    })
    .then((files) => {
        if (!files.length) {
            return Promise.reject(new Error('No source to compile.'));
        }

        return Promise.resolve(true);
    })
    .all([
        rcopyAsync(`${__dirname}/scripting`, 'build'),
        rcopyAsync(`${__dirname}/compiler/${process.platform}`, 'build'),
        rcopyAsync('src/scripting', 'build')
    ])
    .then(() => {
        return globAsync('*.sma', { cwd: 'build' });
    })
    .then((files) => {
        console.log(files);
    })
    .catch(err => {
        throw err;
    });

对于任何感兴趣的人,回调 hell 的工作部分如下:

...

rmrf('{build,dist}', err => {
    if (err) throw err;

    read('src', (err, files) => {
        if (err) throw err;
        if (!files.length) return;

        rcopy(`${__dirname}/scripting`, 'build', err => {
            if (err) throw err;

            rcopy(`${__dirname}/compiler/${process.platform}`, 'build', err => {
                if (err) throw err;

                rcopy('src/scripting', 'build', err => {
                    if (err) throw err;

                    glob('*.sma', { cwd: 'build' }, (err, files) => {
                        if (err) throw err;

                        console.log(files);
                    });
                });
            });
        });
    });
});

最佳答案

您被 promise 的工作原理所欺骗。当您第一次执行 javascript 时,链的所有部分都已构建。因为,在构建您的链时,您调用了 rcopyAsyncrcopyAsync 将立即启动。如果您希望稍后发生某些事情,您需要将其包装在 .then 中。

rmrfAsync('{build,dist}')
.then(() => {
    return readAsync('src');
})
.then((files) => {
    if (!files.length) {
        /* Could even be:
        throw new Error('No source to compile');
        */
        return Promise.reject(new Error('No source to compile.'));
    }
})
.then(() => {
    // Wait until the previous promise finished before starting the rcopyAsync
    return Promise.all([
        rcopyAsync(`${__dirname}/scripting`, 'build'),
        rcopyAsync(`${__dirname}/compiler/${process.platform}`, 'build'),
        rcopyAsync('src/scripting', 'build')
    ]);
})
...

您想推迟执行。如果你在函数包装器之外做一些事情,那么它将立即执行。如果将它放在函数包装器中,它只会在前一个调用完成后执行。

关于javascript - 使用回调 hell 将构建转换为 promise hell ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37039338/

相关文章:

javascript - 使用 mvc4 在谷歌地图中显示位置

eclipse - 在 Eclipse 中运行和调试 Node 项目

javascript - 处理 React Redux 应用程序中的异步错误

javascript - 如何从 Q.when() 解析一系列分辨率?

JavaScript 在函数 'class' 包装器之间进行 promise

javascript - 为下拉菜单添加悬停延迟

javascript - 从共享点检索列表数据

javascript - 如何为使用jquery动态生成的按钮提供唯一的id

javascript - 无法读取未定义的属性 'totalQty'

node.js - 为什么在使用 preset-env node 时无法解析 nodejs 默认模块?