toxic-johann / toxic-johann.github.io

my blog
6 stars 0 forks source link

【2016-02-27】gulp-watch不能监听添加文件 #19

Open toxic-johann opened 7 years ago

toxic-johann commented 7 years ago

这篇文章主要记录下今天做的时候遇到的几个问题。

gulp-watch

第一个问题当然是gulp-watch这个坑。其实这个坑有了很久,大家也很想gulp可以修复这个东西,但是gulp上面已经声明了,这个不是他们的bug。虽然尽力在修,但是不知道什么时候弄得好。

网上也有另外的解决办法,或者直接调用gaze,但是我试了试貌似不行。

所以最后我放弃了,毕竟gulp是拿来监听文件的,不是监听文件夹的。所以我把我的需求变了变,让服务器调用gulp。

这个其实还是很简单的,调用一下exec就好了。

exec('cd ./myblog;gulp markdown;',function(){
    return self.success()
});

这里再次更新一下~~

----------------------------------------我是分割线---------------------------------------------

后来当天回去想了想,觉得这种实现方式实在欠缺优雅。于是我就上网搜了一下node用于监听文件或文件夹变化的组件,最终决定了采用chokidar这个模块。

var chokidar = require('chokidar');

// One-liner for current directory, ignores .dotfiles
chokidar.watch('.', {ignored: /[\/\\]\./}).on('all', (event, path) => {
  console.log(event, path);
});

就这么简单些,就可以监听目前的模块了。然后稍加改变就可以监听模块的改变。

然后就遇到了一个问题。每次模块改变我都触发一个gulp的task,但是如果模块改变的太快,就很可能会在task尚未结束的时候再次启动。这种情况gulp是处理不了的。

所以我就写了一个漏斗来进行逐一处理。

这里顺便提一下,因为涉及到promise的使用,所以我是用了gulp的babel模式,在gulp3.9.0以上会支持。

这里是引自该博文

首先检测一下版本:

gulp -v

版本如下:

CLI version 3.9.0
Local version 3.9.0

如果版本过低可以这么升级

npm install gulp -g && npm install gulp --save-dev

安装babel-loader

npm install babel-core babel-preset-es2015 --save-dev

重点主要是更换命名

mv gulpfile.js gulpfile.babel.js

OK,下面谈谈我的漏斗,漏斗的设计理念其实也还是比较简单的。

  1. 漏斗本身是一个数组,每次只处理数组中的第一个数,处理完后取出第一个数,如果数组中仍有数,处理下一个数。
  2. 漏斗处理的时候,会加锁,但是加锁的时候可以继续添加数,仅仅不能调用处理函数。
  3. 应该可以有多个漏斗存在。

所以我才用了工厂模型。

首先定义一下内部属性

function Funnel () {
    // 定义内部属性
    this.pool = [];
    this.lock = false;
}

然后定义一个_push函数,仅仅用于为pool添加内容,应该可以支持多个数组添加。

this._push = function() {
    let args = [].slice.call(arguments);
    this.pool = this.pool.concat(args);
};

其次定义一个_through函数,用于流通数据,执行函数。此处我才用了promise.

如果被锁或者没数据,不进行处理。否则,加锁,然后进行处理,再解锁。

this._through = function(func){
    if(this.lock || this.pool.length == 0){
        return false;
    }
    this.lock = true;
    func(this.pool[0]).then(function(){
        self._unlock(func)
    })  
};

最后定义一个_unlock函数,用于解锁、取出数据和检测是否需要继续流通。

this._unlock = function(func) {
    this.pool.splice(0,1);
    this.lock = false;
    if(this.pool.length > 0){
        this._through(func)
    }
};

所以最后得到文件Funnel.js

'use strict';
function Funnel () {
    // 定义内部属性
    this.pool = [];
    this.lock = false;
    let self = this;

    // 定义外部方法
    this._push = function() {
        let args = [].slice.call(arguments);
        this.pool = this.pool.concat(args);
    };

    this._through = function(func){
        if(this.lock || this.pool.length == 0){
            return false;
        }
        this.lock = true;
        func(this.pool[0]).then(function(){
            self._unlock(func)
        })
    };

    this._unlock = function(func) {
        this.pool.splice(0,1);
        this.lock = false;
        if(this.pool.length > 0){
            this._through(func)
        }
    };
}

module.exports = Funnel;

然后运用也很简单

let funnel = new Funnel();

gulp.task('default', function () {
    funnel._push(0,1,2,3,4,5,6,7,8,9);
    funnel._through(function(test){
      return new Promise(function(resolve,reject){
        console.log("test",test);
        resolve();
      });
    })     
});

新建一个漏斗,推入数据,然后处理即可。

fs.mkdir

第二个问题是利用生成路径问题。

众所周知,fs.write之类的必须基于已有路径,但是有的时候不一定有,所以我们可以写个函数做个判断。

以前我会这么写

// 创建所有目录
var mkdirs = module.exports.mkdirs = function(dirpath, mode, callback) {
    fs.exists(dirpath, function(exists) {
        if(exists) {
           callback(dirpath);
        } else {
            //尝试创建父目录,然后再创建当前目录
            mkdirs(path.dirname(dirpath), mode, function(){
                 fs.mkdir(dirpath, mode, callback);
            });
        }
    });
};

不过现在我想写成promise可以用,所以我这么写

mkdir:function() {
        let self = this;
        return function(dirpath, mode, callback){
            return new Promise(function(resolve,reject){
                let acallback = (function(dirpath){
                    return function(){
                        if(think.isFunction(callback)){
                            callback(dirpath);
                        }
                        resolve(dirpath);
                    }
                })(dirpath);
                fs.exists(dirpath, function(exists) {
                    if(exists) {
                        acallback(dirpath);
                    } else {
                        self.mkdir(path.dirname(dirpath), mode, function(){
                            fs.mkdir(dirpath, mode, acallback);
                        });
                    }
                });
            });
        }.apply(global.utils,arguments)
    },

我在里面创造了promise并且在callback添加了resolve,从而达到目的。

其实还是有其它方式的,例如你在那个传入的callbak里面绑定一个resolve之类的。不过我主要是懒得做,以后想这么用而已。