前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >node-mkdirp项目源码阅读

node-mkdirp项目源码阅读

作者头像
用户1515472
发布2019-07-25 14:56:44
5780
发布2019-07-25 14:56:44
举报

node-mkdirp是一个linux命令 mkdir -p的node版本,也就是创建多级目录。node-mkdirp值得新手学习的地方在于学习对于错误码的利用和基本的API使用。我曾经也写过一个创建多级目录的方法,不过自己都只是通过split方法对目录分隔开后逐层判断是否存在,再创建。node-mkdirp的方式则是通过fs.mkdir的错误码来判断,挺巧妙的。

var path = require('path');
var fs = require('fs');
var _0777 = parseInt('0777', 8);

module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;

function mkdirP (p, opts, f, made) {
    // 如果opts是函数,则说明这是指定的回调,非函数且非对象则opt是指定的mode
    if (typeof opts === 'function') {
        f = opts;
        opts = {};
    }
    else if (!opts || typeof opts !== 'object') {
        opts = { mode: opts };
    }

    var mode = opts.mode;
    var xfs = opts.fs || fs;

    if (mode === undefined) {
        mode = _0777 & (~process.umask());
    }
    if (!made) made = null;

    var cb = f || function () {};
    p = path.resolve(p);

    // 尝试创建目录,mkdir创建一个不存在的目录时候会返回的错误码是ENOENT
    xfs.mkdir(p, mode, function (er) {
        // 无错误则表明创建的就是最后一级目录了
        if (!er) {
            made = made || p;
            return cb(null, made);
        }
        switch (er.code) {
            // 错误码是ENOENT表明无此文件或目录,则不断尝试创建父级目录
            case 'ENOENT':
                mkdirP(path.dirname(p), opts, function (er, made) {
                    // 无错误则继续尝试创建传入的目录,有错误则说明是已经存在,则直接执行回调
                    if (er) cb(er, made);
                    else mkdirP(p, opts, cb, made);
                });
                break;

            // In the case of any other error, just see if there's a dir
            // there already.  If so, then hooray!  If not, then something
            // is borked.
            // 出现其他错误主要是目录存在,则获取stat
            default:
                xfs.stat(p, function (er2, stat) {
                    // if the stat fails, then that's super weird.
                    // let the original error be the failure reason.
                    if (er2 || !stat.isDirectory()) cb(er, made)
                    else cb(null, made);
                });
                break;
        }
    });
}

mkdirP.sync = function sync (p, opts, made) {
    if (!opts || typeof opts !== 'object') {
        opts = { mode: opts };
    }

    var mode = opts.mode;
    var xfs = opts.fs || fs;

    if (mode === undefined) {
        mode = _0777 & (~process.umask());
    }
    if (!made) made = null;

    p = path.resolve(p);

    // 同步版本类似于异步版本的处理,不过需要使用try...catch...来捕捉错误
    try {
        xfs.mkdirSync(p, mode);
        made = made || p;
    }
    catch (err0) {
        switch (err0.code) {
            case 'ENOENT' :
                made = sync(path.dirname(p), opts, made);
                sync(p, opts, made);
                break;

            // In the case of any other error, just see if there's a dir
            // there already.  If so, then hooray!  If not, then something
            // is borked.
            default:
                var stat;
                try {
                    stat = xfs.statSync(p);
                }
                catch (err1) {
                    throw err0;
                }
                if (!stat.isDirectory()) throw err0;
                break;
        }
    }

    return made;
};
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档