模块化的发展

function m1(){
  //...
}
function m2(){
  //...
}
var module1 = new Object({
  _count: 0,
 m1: function (){
    //...
  },
  m2: function (){
    //...
  }
});
(function () {
 var m1 = function (){
    //...
  };
  var m2 = function (){
    //...
  };
}());
var module1 = (function(){
  var _count = 0;
 var _m1 = function (){
    //...
  };
  var _m2 = function (){
    //...
  };
  return {
    m1: _m1,
    m2: _m2
  };
});
var module1 = (function (mod){
  mod.m3 = function () {
    //...
  };
  return mod;
})(module1);
var module1 = (function ($) {
  //...
})(jQuery);

CommonJS

CommonJS定义的模块分为:{模块引用(require)} {模块定义(exports)} {模块标识(module)}
require()用来引入外部模块;exports对象用于导出当前模块的方法或变量,唯一的导出口;module对象就代表模块本身。

const http = require('http');

http.createServer( (request, response) => {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(12880);

console.log('Server running at http://127.0.0.1:12880/');

AMD

Asynchronous Module Definition

require([module], callback);

require.js
curl.js

// main.js
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
  // some code here
});
require(['jquery', 'underscore', 'backbone'], function ($, _, bb){
  // some code here
});
require.config({
  paths: {
    "jquery": "libs/jquery.min",
    "underscore": "libs/underscore.min",
    "backbone": "libs/backbone.min"
  }
});
// math.js
define(function (){
  var add = function (x,y){
    return x+y;
  };
  return {
    add: add
  };
});
require.config({
  shim: {
    'underscore':{
      exports: '_'
    },
    'backbone': {
      deps: ['underscore', 'jquery'],
      exports: 'Backbone'
    }
  }
});

Thrift

Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码

IDL

类型

基本类型

  • bool: 布尔类型
  • byte: 有符号字节
  • i16: 16位有符号整型
  • i32: 32位有符号整型
  • i64: 64位有符号整型
  • double: 64位浮点数
  • string: 未知编码或者二进制的字符串

thrift不支持无符号整型

容器类型

  • List:一系列T类型的元素组成的有序表,元素可以重复
  • Set:一系列T类型的元素组成的无序表,元素唯一
  • Map<K,V>:key/value对,key的类型是K且key唯一,value类型是V

容器中的元素类型可以是除了service外的任何合法thrift类型(包括结构体和异常)

结构体

Thrift结构体在概念上同C语言结构体类型。在面向对象语言中,thrift结构体被转换成类。

struct Tweet {
  1: required i32 userId;                  //每个域有一个唯一的,正整数标识符
  2: required string userName;             //每个域可以标识为required或者optional,也可以不注明
  3: required string text;
  4: optional Location loc;                //结构体可以包含其他结构体
  16: optional string language = "english" //域可以有缺省值
}
 
struct Location {                          //一个thrift中可定义多个结构体,并存在引用关系
  1: required double latitude;
  2: required double longitude;
}

规范的struct定义中的每个域均会使用required或者optional关键字进行标识。如果required标识的域没有赋值,thrift将给予提示。如果optional标识的域没有赋值,该域将不会被序列化传输。如果某个optional标识域有缺省值而用户没有重新赋值,则该域的值一直为缺省值。 与service不同,结构体不支持继承。

异常

异常在语法和功能上类似于结构体,只不过异常使用关键字exception而不是struct关键字声明。当定义一个RPC服务时,开发者可能需要声明一个远程方法抛出一个异常。

服务

服务的定义方法在语法上等同于面向对象语言中定义接口。Thrift编译器会产生实现这些接口的client和server桩。 在流行的序列化/反序列化框架(如protocol buffer)中,thrift是少有的提供多语言间RPC服务的框架。 Thrift编译器会根据选择的目标语言为server产生服务接口代码,为client产生桩代码。

service Twitter {                               //"Twitter"与"{"之间需要有空格
//方法定义方式类似于C语言中的方式,它有一个返回值,一系列参数和可选的异常列表  
//参数列表和异常列表定义方式与结构体中域定义方式一致  
  void ping(),                                    //函数定义可以使用逗号或者分号标识结束
  bool postTweet(1:Tweet tweet);                  //参数可以是基本类型或者结构体,参数是只读的
  TweetSearchResult searchTweets(1:string query); //返回值可以是基本类型或者结构体
  //"oneway"标识符表示client发出请求后不必等待回复(非阻塞)直接进行下面的操作,
  //"oneway"方法的返回值必须是void
  oneway void zip()                               //返回值可以是void
 
}

函数中参数列表的定义方式与struct完全一样 Service支持继承,一个service可使用extends关键字继承另一个service

类型定义

Thrift支持C/C++风格的typedef

typedef i32 MyInteger   \\末尾没有逗号  
typedef Tweet ReTweet   \\struct可以使用typedef

枚举类型

可以像C/C++那样定义枚举类型,如:

enum TweetType {
  TWEET,       //编译器默认从0开始赋值
  RETWEET = 2, //可以赋予某个常量某个整数
  DM = 0xa,    //允许常量是十六进制整数
  REPLY        //末尾没有逗号
}
 
struct Tweet {
  1: required i32 userId;
  2: required string userName;
  3: required string text;
  4: optional Location loc;
  5: optional TweetType tweetType = TweetType.TWEET //给常量赋缺省值时,使用常量的全称
  16: optional string language = "english"
}

不同于protocol buffer,thrift不支持枚举类嵌套,枚举常量必须是32位的正整数

注释

Thrfit支持shell注释风格,C/C++语言中单行或者多行注释风格

# This is a valid comment.
/*
* This is a multi-line comment.
* Just like in C.
*/
// C++/Java style single-line comments work just as well.

命名空间

Thrift中的命名空间同C++中的namespace和java中的package类似,它们均提供了一种组织(隔离)代码的方式。因为每种语言均有自己的命名空间定义方式(如python中有module),thrift允许开发者针对特定语言定义namespace:

namespace cpp com.example.project  //转化成namespace com { namespace example { namespace project {
namespace java com.example.project //转换成package com.example.project

文件包含

Thrift允许thrift文件包含,用户需要使用thrift文件名作为前缀访问被包含的对象,如:

include "tweet.thrift"          //thrift文件名要用双引号包含,末尾没有逗号或者分号
...
struct TweetSearchResult {
  1: list<tweet.Tweet> tweets;  //注意tweet前缀
}

常量

Thrift允许用户定义常量,复杂的类型和结构体可使用JSON形式表示。

const i32 INT_CONST = 1234;    //分号是可选的,可有可无;支持十六进制赋值
const map<string,string> MAP_CONST = {"hello": "world", "goodnight": "moon"}

支持语言

网络模型

  +-------------------------------------------+
  | Server                                    |
  | (single-threaded, event-driven etc)       |
  +-------------------------------------------+
  | Processor                                 |
  | (compiler generated)                      |
  +-------------------------------------------+
  | Protocol                                  |
  | (JSON, compact etc)                       |
  +-------------------------------------------+
  | Transport                                 |
  | (raw TCP, HTTP etc)                       |
  +-------------------------------------------+

传输格式

  • TBinaryProtocol: 二进制格式
  • TCompactProtocol: 压缩格式
  • TJSONProtocol: JSON格式
  • TSimpleJSONProtocol: 提供JSON只写协议, 生成的文件很容易通过脚本语言解析
  • TDebugProtocol: 使用易懂的可读的文本格式,以便于debug

    数据传输方式

  • TSocket: 阻塞式socker
  • TFramedTransport: 以frame为单位进行传输,非阻塞式服务中使用
  • TFileTransport: 以文件形式进行传输
  • TMemoryTransport: 将内存用于I/O. java实现时内部实际使用了简单的ByteArrayOutputStream
  • TZlibTransport: 使用zlib进行压缩, 与其他传输方式联合使用。当前无java实现

    服务模型

  • TSimpleServer: 简单的单线程服务模型,常用于测试
  • TThreadPoolServer: 多线程服务模型,使用标准的阻塞式IO
  • TNonblockingServer: 多线程服务模型,使用非阻塞式IO,需使用TFramedTransport数据传输方式

Node.js

Node.js采用了Google Chrome浏览器的V8引擎,性能很好,同时还提供了很多系统级的API,如文件操作、网络编程等

Node.js采用事件驱动、异步编程,为网络服务而设计

Node.js以单进程、单线程模式运行

Node.js Documentation

Node.js异步编程风格

MEAN

MongoDB

Express

Angular.js

Debug

logging

console + forever | pm2

forever start app.js
pm2 start app.js

Winston

const winston = require('winston');
 
winston.log('info', 'Hello distributed log files!');
winston.info('Hello again distributed logs');
winston.info('Hello world!', {timestamp: Date.now(), pid: process.pid});
winston.log('info', 'tHello number: %d', 123);
const winston = require('winston');
const logger = new winston.Logger();
 
logger.log('info', 'Hello distributed log files!');
logger.info('Hello again distributed logs');
winston.loggers.add('category1', {console: { ... }, file: { ... }});
winston.loggers.add('category2', {irc: { ... }, file: { ... }});

Bunyan

var bunyan = require('bunyan');
var log = bunyan.createLogger({name: 'myapp'});
log.info('hi');
log.warn({lang: 'fr'}, 'au revoir');

  1. 多线程有什么用?
  2. 创建线程的方式
  3. start方法和run方法的区别
  4. Runnable接口和Callable接口的区别
  5. CyclicBarrier和CountDownLatch的区别
  6. Volatile关键字的作用
  7. 什么是线程安全
  8. Java中如何获取到线程dump文件
  9. 一个线程如果出现了运行时异常会怎么样
  10. 如何在两个线程之间共享数据
  11. sleep方法和wait方法有什么区别
  12. 生产者消费者模型的作用是什么
  13. ThreadLocal有什么用
  14. 为什么wait方法和notify/notifyAll方法要在同步块中被调用
  15. wait方法和notify/notifyAll方法在放弃对象监视器时有什么区别
  16. 为什么要使用线程池
  17. 怎么检测一个线程是否持有对象监视器
  18. synchronized和ReentrantLock的区别
  19. ConcurrentHashMap的并发度是什么
  20. ReadWriteLock是什么
  21. FutureTask是什么
  22. Linux环境下如何查找哪个线程使用CPU最长
  23. Java编程写一个会导致死锁的程序
  24. 怎么唤醒一个阻塞的线程
  25. 不可变对象对多线程有什么帮助
  26. 什么是多线程的上下文切换
  27. 如果你提交任务时,线程池队列已满,这时会发生什么
  28. Java中用到的线程调度算法是什么
  29. Thread.sleep(0)的作用是什么
  30. 什么是自旋
  31. 什么是happens-before,即先行发生原则
  32. 什么是CAS
  33. 什么是乐观锁和悲观锁
  34. 什么是AQS
  35. 单例模式的线程安全性
  36. Semaphore有什么作用
  37. Hashtable的size方法中明明只有一条语句”return count”,为什么还要做同步?
  38. 线程类的构造方法、静态块是被哪个线程调用的
  39. 同步方法和同步块,哪个是更好的选择
  40. 高并发、任务执行时间短的业务怎样使用线程池?并发不高、任务执行时间长的业务怎样使用线程池?并发高、业务执行时间长的业务怎样使用线程池?

文档类型

<!DOCTYPE html>
<html lang="zh-CN">
  ...
</html>

移动优先

<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

scaffolding.less

Normalize.css

布局容器

<div class="container">
  ...
</div>
<div class="container-fluid">
  ...
</div>

石器时代

JsUnit

Unit.js

iMacros

铜器时代

QUnit

API Documentation
Cookbook

Selenium

铁器时代

Jasmine

Jasmine is a behavior-driven development framework for testing JavaScript code.

Mocha

Mocha is a feature-rich JavaScript test framework running on Node.js and the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases.

PhantomJS

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

Karma

The main goal for Karma is to bring a productive testing environment to developers. The environment being one where they don’t have to set up loads of configurations, but rather a place where developers can just write the code and get instant feedback from their tests.

Nightwatch.js

Write End-to-End tests in Node.js quickly and effortlessly that run against a Selenium server.

WebdriverIO

Selenium 2.0 bindings for NodeJS