首页 > 解决方案 > 在异步代码中运行同步代码 - 承诺

问题描述

我使用带有承诺的以下代码,困扰我的事情是我使用readdirsyncfs.statSync 内部承诺,它可能是错的,我问它,因为目前它按预期工作但我想知道我是否可以遇到问题。或者有更好的方法写吗?

我所做的是提取根文件夹,然后提取 Childs

function unzip(filePath, rootP, fileN) {

    return new Promise((resolve, reject) => {
        extract(filePath, {dir: rootP, defaultDirMode: '0777'}, (err) => {
            if (err) {
                reject(err);
            }
            fs.readdirSync(path.join(rootP, fileN
)).forEach((file) => {
                const zipPath = path.join(rootP, fileN
, file);
                if (fs.statSync(zipPath).isFile()) {
                    if (path.extname(file) === '.zip') {
                        let name = path.parse(file).name;
                        let rPath = path.join(rootP, fileN)
                        return unzipChilds(zipPath, rPath, name)
                            .then(() => {
                                return resolve(“Done");
                            });
                    }
                }
            });

        });

    });
}

标签: javascriptnode.jsasynchronouspromise

解决方案


我建议使用 Promises 和async/await你的所有逻辑流程,如下所示:

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

async function unzip(filePath, rootP, fileN) {
    await extractAsync(filePath, {dir: rootP, defaultDirMode: '0777'});
    let files = await fs.readdirAsync(path.join(rootP, fileN));
    for (let file of files) {
        const zipPath = path.join(rootP, fileN, file);
        let stats = await fs.statAsync(zipPath);
        if (stats.isFile() && path.extname(file) === '.zip') {
            let name = path.parse(file).name;
            let rPath = path.join(rootP, fileN);
            await unzipChilds(zipPath, rPath, name);
        }
    }
}

// usage:
unzip(...).then(() => {
    // all done here
}).catch(err => {
    // process error here
});

好处:

  1. 一致和完整的错误处理。您的版本有多个地方没有正确处理错误。
  2. 所有异步 I/O,因此不会干扰服务器的扩展。
  3. async/await使异步逻辑流程更易于遵循

推荐阅读