分类:代码

码农是第一生产力。

docker 加速器配置方法

  • ubuntu
apt install docker docker-compose
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://srdqkbud.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
  • docker toolbox (win7)
docker-machine ssh default 
sudo sed -i "s|EXTRA_ARGS='|EXTRA_ARGS='--registry-mirror=https://srdqkbud.mirror.aliyuncs.com |g" /var/lib/boot2docker/profile 
exit 
docker-machine restart default
  • docker for windows (win10)
--registry-mirror=https://srdqkbud.mirror.aliyuncs.com

{
  "registry-mirrors": [
    "https://srdqkbud.mirror.aliyuncs.com"
  ],
  "insecure-registries": [],
  "debug": false
}

ubuntu 启动进入 console

vim /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="text"
GRUB_TERMINAL=console
update-grub
systemctl set-default multi-user.target

angular5 可用的 WebWorker ThreadPool

  • 完整代码
    • Test Code

       for (let i = 0; i < 10; ++i) {
        const workerTask = new WorkerTask('worker3.js', String(i))
        this.threadPool.addWorkerTask(workerTask)
          .subscribe(
            data => console.log(data),
            err => console.log('err:' + err),
            () => console.log(i + ':finish')
          );
      }
      
    • Web Worker

      import {Observable} from 'rxjs/Observable';
      import 'rxjs/add/observable/timer';
      
      interface DedicatedWorkerGlobalScope extends Window {
        postMessage(data: string): void;
        close(): void;
      }
      
      onmessage = function (e) {
        Observable.timer(1000).subscribe(data => {
          const self = this as DedicatedWorkerGlobalScope;
          for (let i = 0; i < 10; ++i) {
            self.postMessage(e.data + ':' + i);
          }
          self.postMessage('done');
          self.close();
        });
      };    
      
    • ThreadPoolService

      import {Injectable} from '@angular/core';
      import {Observable} from 'rxjs/Observable';
      
      export class WorkerTask {
        public observer;
      
        constructor(public script: string,
                    public startMessage: string) {
        }
      }
      
      class WorkerThread {
        private workerTask: WorkerTask;
      
        constructor(private parentPool: ThreadPoolService) {
        }
      
        public run(workerTask: WorkerTask) {
          this.workerTask = workerTask;
          // create a new web worker
          if (this.workerTask.script != null) {
      
            const worker = new Worker(workerTask.script);
            worker.addEventListener('message', event => this.dummyCallback(event), false);
            worker.postMessage(workerTask.startMessage);
          }
        }
      
        // for now assume we only get a single callback from a worker
        // which also indicates the end of this worker.
        public dummyCallback(event) {
          let done = false;
          // pass to original callback
          if ('data' in event) {
            this.workerTask.observer.next(event.data);
            if (event.data === 'done') {
              done = true;
              this.workerTask.observer.complete();
            }
          } else {
            this.workerTask.observer.error(event);
            done = true;
          }
      
          // we should use a seperate thread to add the worker
          if (done) {
            this.parentPool.freeWorkerThread(this);
          }
        }
      }
      
      @Injectable()
      export class ThreadPoolService {
      
        private taskQueue: WorkerTask[] = [];
        private threadQueue: WorkerThread[] = [];
        private poolSize = 5;
      
        constructor() {
          for (let i = 0; i < this.poolSize; i++) {
            this.threadQueue.push(new WorkerThread(this));
          }
        }
      
        public setSize(size: number) {
          this.poolSize = size;
      
          this.threadQueue = [];
          for (let i = 0; i < size; i++) {
            this.threadQueue.push(new WorkerThread(this));
          }
        }
      
        public addWorkerTask(workerTask: WorkerTask) {
          return Observable.create(observer => {
            workerTask.observer = observer;
      
            if (this.threadQueue.length > 0) {
              // get the worker from the front of the queue
              const workerThread = this.threadQueue.shift();
              workerThread.run(workerTask);
            } else {
              // no free workers,
              this.taskQueue.push(workerTask);
            }
          });
        }
      
        public freeWorkerThread(workerThread: WorkerThread) {
          if (this.taskQueue.length > 0) {
            // don't put back in queue, but execute next task
            const workerTask = this.taskQueue.shift();
            workerThread.run(workerTask);
          } else {
            this.threadQueue.push(workerThread);
          }
        }
      }
      
  • 难点分析
worker.addEventListener('message', event => this.dummyCallback(event), false);

第二个参数,如果写成 this.dummyCallback ,则回调时,this 环境已经变化,代码运行异常。 event => this.dummyCallback(evnet) 是 es5 的语法,用来绑定 this,es6 的语法可以写成 this.dummyCallback.bind(tihs)

angular5 手工注入 HttpClient

  • 手工注入 HttpClient
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {ReflectiveInjector, Type} from '@angular/core';

const injector = ReflectiveInjector.resolveAndCreate(getAnnotations(HttpClientModule)[0].providers);
const httpClient = injector.get(HttpClient);

httpClient.get('www.baidu.com', {responseType: 'text'})
  .subscribe(resp => {
      console.log('resp');
    }
  );

  • 辅助函数
declare let Reflect: any;

function getAnnotations(typeOrFunc: Type<any>): any[] | null {
  // Prefer the direct API.
  if ((<any>typeOrFunc).annotations) {
    let annotations = (<any>typeOrFunc).annotations;
    if (typeof annotations === 'function' && annotations.annotations) {
      annotations = annotations.annotations;
    }
    return annotations;
  }

  // API of tsickle for lowering decorators to properties on the class.
  if ((<any>typeOrFunc).decorators) {
    return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators);
  }

  // API for metadata created by invoking the decorators.
  if (Reflect && Reflect.getOwnMetadata) {
    return Reflect.getOwnMetadata('annotations', typeOrFunc);
  }
  return null;
}

function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] {
  if (!decoratorInvocations) {
    return [];
  }
  return decoratorInvocations.map(decoratorInvocation => {
    const decoratorType = decoratorInvocation.type;
    const annotationCls = decoratorType.annotationCls;
    const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
    return new annotationCls(...annotationArgs);
  });
}

angular5 编译单独 typescript 文件方法

安装 gulp 及相关组件

npm install gulp -g
npm install gulp-typescript gulp-sourcemaps gulp-uglify browserify vinyl-source-stream vinyl-buffer tsify glob gulp-rename event-stream

在根目录下添加 gulpfile.js 文件

gulp = require('gulp');
ts = require('gulp-typescript');
exec = require('child_process').exec;
browserify = require("browserify");
source = require('vinyl-source-stream');
buffer = require('vinyl-buffer');
uglify = require('gulp-uglify');
sourcemaps = require('gulp-sourcemaps');
tsify = require("tsify");
es = require('event-stream');
rename = require('gulp-rename');
glob = require('glob');

gulp.task('ng-build', function (cb) {
  console.log('running ng build...');
  exec('ng build', function (err, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
    cb(err);
    return true;
  });
});

function tstojs(entry) {
  return browserify({
    basedir: '.',
    debug: true,
    entries: [entry]
  })
    .plugin(tsify)
    .bundle()
    .pipe(source(entry))
    .pipe(rename({
      dirname: './',
      extname: '.js'
    }))
    .pipe(buffer())
    .pipe(sourcemaps.init({
      loadMaps: true
    }))
    .pipe(uglify())
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest('./dist/'));
}

gulp.task('worker', function (done) {
  console.log('compiling ts to js')
  glob('./src/worker/*.ts', function (err, files) {
    if (err) done(err);

    var tasks = files.map(function (entry) {
      return tstojs(entry);
    });
    es.merge(tasks).on('end', done);
  });
});

gulp.task('watch', function () {
  // gulp.watch('./src/worker/*.ts', ['worker']);
  gulp.watch('./src/worker/*.ts', function (o) {
    return tstojs(o.path);
  });
})

gulp.task('default', [
  'ng-build',
  'worker'
]);

编译方法

  • 全部编译: gulp
  • 编译 worker: gulp worker
  • 监视编译: gulp watch