安装配置 anyproxy

(wxenv) williamtekiMacBook-Pro:weixin_crawler valentine$ npm install -g anyproxy
npm WARN deprecated clipboard-js@0.3.6: Please migrate to https://github.com/lgarron/clipboard-polyfill
/usr/local/bin/anyproxy -> /usr/local/lib/node_modules/anyproxy/bin/anyproxy
/usr/local/bin/anyproxy-ca -> /usr/local/lib/node_modules/anyproxy/bin/anyproxy-ca
npm WARN svg-inline-react@1.0.3 requires a peer of react@^0.14.0 || ^15.0.0 but none is installed. You must install peer dependencies yourself.

+ anyproxy@4.0.12
added 237 packages from 273 contributors in 50.829s
(wxenv) williamtekiMacBook-Pro:weixin_crawler valentine$ anyproxy
[AnyProxy Log][2019-01-21 14:07:17]: Http proxy started on port 8001
[AnyProxy Log][2019-01-21 14:07:17]: web interface started on port 8002
^C[AnyProxy Log][2019-01-21 14:10:01]: clearing cache file...
[AnyProxy Log][2019-01-21 14:10:01]: ==>>> clearing cache
[AnyProxy Log][2019-01-21 14:10:01]: closing webserver...
(wxenv) williamtekiMacBook-Pro:weixin_crawler valentine$ anyproxy-ca
detecting CA status...
AnyProxy CA does not exist.
? Would you like to generate one ? Yes
temp certs cleared
rootCA generated
PLEASE TRUST the rootCA.crt in /Users/valentine/.anyproxy/certificates
The cert is generated at /Users/valentine/.anyproxy/certificates. Please trust the rootCA.crt.
(wxenv) williamtekiMacBook-Pro:weixin_crawler valentine$

配置系统证书认证确认

2019/1/21 posted in  web

可拖拽前端框架分析

layoutit框架
可以设置布局类型的可托转框架,不是可任意拖拽的,二是使用Bootstrap类似的框架模式进行的。

gridstack
可以拖拽的Table类型拖拽框架,不是随意放置
感觉redash是使用的这个框架。

maqetta
这个可以研究一下,感觉封装的比较严,而不是一个基础库,已经是一个工具了。

VisualUIEditor
基于electron的可视化UI编辑器,这个是基于electron来做的,可以研究里面使用的哪个开源组件来实现的,就可以实现web版本了。

适用于仪表盘项目的7个优秀JavaScript库

2019/1/12 posted in  web

redux 知识整理

redux文档

基础知识

基本思想

State,记录应用的状态。
Action,记录对应用的动作,描述发生了什么
reducer,reducer接收state和action,并返回新的state函数。

核心概念

state : 普通对象,类似一个json串,或者类似Model,存储当前的数据状态

{
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

action: 要像更新state中的数据,需要发起一个action。action就像是描述发生了什么的指示器。

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

reducer: reducer只是一个接收state和action,并返回新的state的函数。对于大的应用来说,不大可能仅仅只写一个这样的函数,所以我们编写很多小函数来分别管理 state 的一部分。

function visibilityFilter(state = 'SHOW_ALL', action) {
  if (action.type === 'SET_VISIBILITY_FILTER') {  //这里的判断为当为指定类型的action的时候,处理特定方法来返回state
    return action.filter;
  } else {
    return state;
  }
}

function todos(state = [], action) {
  switch (action.type) {
  case 'ADD_TODO':
    return state.concat([{ text: action.text, completed: false }]); //给state增加内容
  case 'TOGGLE_TODO':
    return state.map((todo, index) =>
      action.index === index ?
        { text: todo.text, completed: !todo.completed } :
        todo
   )
  default:
    return state;
  }
}

三大原则

  1. 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
  2. State 是只读的,唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
  3. 使用纯函数来执行修改,刚开始你可以只有一个 reducer,随着应用变大,你可以把它拆成多个小的 reducers,分别独立地操作 state tree 的不同部分

基础

Action

  1. Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。
  2. Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。
  3. Redux 中只需把 action 创建函数的结果传给 dispatch() 方法即可发起一次 dispatch 过程

Reducer

  1. Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
  2. 现在我们已经确定了 state 对象的结构,就可以开始开发 reducer。reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。
  3. 在高级篇里会介绍如何执行有副作用的操作。现在只需要谨记 reducer 一定要保持纯净。只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。

Store

Store 就是把它们联系到一起的对象。Store 有以下职责:

维持应用的 state;
提供 getState() 方法获取 state;
提供 dispatch(action) 方法更新 state;
通过 subscribe(listener) 注册监听器;
通过 subscribe(listener) 返回的函数注销监听器。
再次强调一下 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合 而不是创建多个 store。

数据流

  1. 调用 store.dispatch(action)

Action 就是一个描述“发生了什么”的普通对象。比如:


 { type: 'LIKE_ARTICLE', articleId: 42 }
 { type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Mary' } }
 { type: 'ADD_TODO', text: 'Read the Redux docs.' }
  1. Redux store 调用传入的 reducer 函数。

Store 会把两个参数传入 reducer: 当前的 state 树和 action。例如,在这个 todo 应用中,根 reducer 可能接收这样的数据:

 // 当前应用的 state(todos 列表和选中的过滤器)
 let previousState = {
   visibleTodoFilter: 'SHOW_ALL',
   todos: [
     {
       text: 'Read the docs.',
       complete: false
     }
   ]
 }

 // 将要执行的 action(添加一个 todo)
 let action = {
   type: 'ADD_TODO',
   text: 'Understand the flow.'
 }

 // reducer 返回处理后的应用状态
 let nextState = todoApp(previousState, action)
  1. 根 reducer 应该把多个子 reducer 输出合并成一个单一的 state 树。

  2. Redux store 保存了根 reducer 返回的完整 state 树。

2018/12/6 posted in  web

Gank代码分析

主要分析js中的代码

  1. actions 存储所有的actions行为
    1. actionTypes.js action类型的常量定义,全局action常量
    2. handleCollectionData.js action的具体定义
    3. modifySettings.js
    4. requestCategoryData.js 调用接口获取目录数据
    5. requestHomeData.js 调用接口获取主页数据
    6. requestRandomData.js
  2. assets 图片放在这里
  3. components 定义公用的页面组件
    1. Avatar.js 所有的图标都走这个文件,后面使用,在其他页面引用使用
    2. BackPageComponent.js
    3. ListViewFooter.js 定义
      标签
    4. ListViewForCategory.js
    5. ListViewForCollection.js 定义标签,在首页使用
    6. ListViewForGirls.js
    7. ListViewForHome.js
    8. NavigationBar.js
    9. RowItemWithSwitcher.js
    10. SimpleRowItem.js
  4. constants 定义常量,颜色常量、后台绑定数据常量等
    1. colors.js 定义不同的颜色主题,在APP选择主题的地方可以选择
    2. fetchUrl.js 定义和后台数据绑定的url 这个使用的接口方式是直接get访问,不带任何token类型的,也不鉴权,后面这一块需要加上。
    3. theme.js 定义主题的颜色
  5. containers 定义各个页面的展示内容
    1. CollectionTab 收藏页面
    2. DiscoveryTab 发现页面
      1. GirlsPage.js 福利页面
      2. index.js 发现的首页
      3. TextListPage.js 前端数据页面
      4. VideoTabPage.js 休息视频页面
    3. HomeTab 主页
      1. index.js 主页
    4. MoreTab 更多的页面信息
      1. AboutAuthorPage.js 关于作者页面
      2. AboutGankPage.js 关于Gank
      3. index.js 更多页面配置
      4. OrderContentPage.js
      5. ThemeColorPage.js 主题颜色页面
    5. MainPage.js
    6. WebViewPage.js
  6. dao 存储数据,这个使用的存储是放在AsyncStorage中的,不同的数据指定不同的key存储
    1. FavouriteDataDAO.js
    2. HomeDataDAO.js
    3. RandomDataDAO.js
    4. SettingDataDAO.js
  7. native_modules
  8. reducers 定义不同的reducers
    1. categoryDataState.js
    2. favorDataState.js
    3. homeDataState.js
    4. index.js
    5. randomDataState.js
    6. settingState.js
  9. store 定义store
    1. index.js 使用中间件定义store
  10. utils
    1. fetchWithTimeout.js 设置读取超时时间
    2. getData.js 获取时间的工具
    3. handleHomeDataSource.js 获取目标页面的datasource (从这里可以看出来,所有的datasource是写在results的子集下面的)
    4. imageFactory.js 图片圆角工具
    5. px2dp.js px像素转化dp的工具
    6. shareUtil.js 分享工具
  11. App.js
2018/12/5 posted in  web

ReactNative IOS 指定版本运行

可以使用xcrun来运行查看具体的版本

williamtekiMacBook-Pro:react-native-Gank valentine$ xcrun simctl list devices
== Devices ==
-- iOS 12.1 --
    iPhone 5s (6199ADBB-CB0E-4CDB-8950-A871F1DA9CF0) (Shutdown)
    iPhone 6 (00AB9AE8-E128-4C10-9D62-570250772E8D) (Booted)
    iPhone 6 Plus (E69D1237-B032-4AEF-A813-74637DCBBB39) (Shutdown)
    iPhone 6s (26894AEF-9D10-40CC-B137-293C0252A6F5) (Shutdown)
    iPhone 6s Plus (7A137B77-3E03-473C-B2EE-F2721CD599E7) (Shutdown)
    iPhone 7 (308F8F53-7C35-44F3-9749-D1A27EB83F0D) (Shutdown)
    iPhone 7 Plus (781E31F0-5ABD-472A-BEEE-4184FD41FE67) (Shutdown)
    iPhone 8 (2994B9EF-2EF3-4907-B0BC-A3BA1237CC98) (Shutdown)
    iPhone 8 Plus (F4C073DC-32AB-40E9-8E3B-7390C29697AD) (Shutdown)
    iPhone SE (A95F1C9A-A574-4D87-8BCF-E8F772A01E63) (Shutdown)
    iPhone X (6394A4CF-E2DD-42D1-BAA7-A750EC6FFD7F) (Shutdown)
    iPhone XS (ED451917-64D1-450C-8BF7-FACE896A9985) (Shutdown)
    iPhone XS Max (CEA9C873-9B8B-4153-8095-5F0BEDE8AACE) (Shutdown)
    iPhone XR (38156FC2-A003-4764-A290-AC122F356BB1) (Shutdown)
    iPad Air (E6ADEDFF-C380-40CF-B39E-1A18C421C169) (Shutdown)
    iPad Air 2 (CA3F1EF9-B5D8-402D-97E0-497B15D30E1F) (Shutdown)
    iPad (5th generation) (3459FC77-D370-4082-81AD-2EF8A93D0E03) (Shutdown)
    iPad Pro (9.7-inch) (5ED82ADE-A8CF-4111-9F41-79350B2279BB) (Shutdown)
    iPad Pro (12.9-inch) (DF32A188-7A36-44D8-A3FD-2876A121CB10) (Shutdown)
    iPad Pro (12.9-inch) (2nd generation) (18B3B724-D907-4A04-AF8E-DD8BD15FBA6D) (Shutdown)
    iPad Pro (10.5-inch) (FD76F0D2-3D7A-4827-9319-B910CF8EA4BF) (Shutdown)
    iPad (6th generation) (4AD10639-51B2-407C-8F1E-0C90A6A6EFFC) (Shutdown)
    iPad Pro (11-inch) (23301F25-2B2D-40F2-8FCC-DAB30A2CDD47) (Shutdown)
    iPad Pro (12.9-inch) (3rd generation) (44A5B520-2930-48CB-9D2F-10F7FC74713E) (Shutdown)
-- tvOS 12.1 --
    Apple TV (C93717D7-B1B8-4116-AE7D-4C7A1DF6FBE7) (Shutdown)
    Apple TV 4K (0F4E46DF-35F3-423B-BDD8-4452C5A12D5C) (Shutdown)
    Apple TV 4K (at 1080p) (2C847CB7-5122-4330-BA7A-69ABA7D607F2) (Shutdown)
-- watchOS 5.1 --
    Apple Watch Series 2 - 38mm (CC6C55FE-D942-4DCF-BB9D-3775CB9851D3) (Shutdown)
    Apple Watch Series 2 - 42mm (36C5051E-69D0-47CB-A026-8C54554993A9) (Shutdown)
    Apple Watch Series 3 - 38mm (7DC891D9-A549-4E57-9249-CFE4EA805A20) (Shutdown)
    Apple Watch Series 3 - 42mm (BA5680EA-BDBA-472A-8D71-DE4974CAEDBF) (Shutdown)
    Apple Watch Series 4 - 40mm (7345AF43-04DC-45AD-9CF0-D40A1CF59BF4) (Shutdown)
    Apple Watch Series 4 - 44mm (4F1DC43F-F85E-4CA8-83E9-7A8C43A028CD) (Shutdown)

方法与android 相同,但是有个小问题
Debug 时会调用 react-native run ios命令,而这个命令默认会拉起iPhone 6的模拟器。并且系统版本还会选择现有的较低版本。有时候程序会直接因为版本太低无法运行。
只时候我们可以改一下这个命令的默认配置。
打开porject/node_modules/react-native/local-cli/runIOS/runIOS.js
在module.export 中找到options ,修改其中的Default为别的机型,比如iPhoneX,再次运行就可以默认使用iPhoneX机型Debug了
{
command: '--simulator [string]',
description: 'Explicitly set simulator to use',
default: 'iPhone X',
},

注意使用React Native Tools 进行Debug的时候,先要关闭网页的Debug。否则会提示
Could not debug. Another debugger is already connected to packager. Please close it before trying to debug with VSCode.
这时候,在行内打印断点,可以在下面的控制台查看变量进行调试,也可以用最上面的菜单栏控制Debug的步揍

参考文章:

React Native使用VSCode 进行 Debug

2018/12/5 posted in  web

ReactNative Android 真机调试

本篇主要是解决在mac下配置ReactNative Android下面的真机调试配置

ReactNative

1. 安装Android SDK Manager

下载地址

下载完成后进入tools目录下执行./android sdk,打开Manager界面

首先把一些必须要安装的SDK安装了

  1. Android SDK Tools
  2. Android SDK Platform-tools
  3. Android SDK Build-tools
  4. Android 8.0.0下的SDK-Platform 这个可以根据具体要发布的版本来进行安装
  5. Extra下的Android Support Repository

这几个是必须安装的,否则打包的时候会报错

2. 配置环境变量

最好的方式是配置环境变量到touch ~/.bash_profile里面,我由于硬盘不够,装在U盘上,如果写在里面加载的时候可能会出现问题,所以每次需要使用的时候手动加载一下环境变量吧

/**
网上很多地方写的Android SDK的位置在/Users/xxxx/Library/Android/sdk 目录下,这个是在手动安装了Android Studio之后才会有的,我们这里没有安装Android Studio,所以没有这个配置文件。配置Android Home是直接写到android-sdk-manager-macosx的目录下。
*/
export PATH=${PATH}:/Volumes/UDisk32G/android-sdk-manager-macosx/platform-tools/
export PATH=${PATH}:/Volumes/UDisk32G/android-sdk-manager-macosx/tools/
export ANDROID_HOME=/Volumes/UDisk32G/android-sdk-manager-macosx/ 
//

export PATH=${PATH}:/Volumes/WD1TExtensi/tools/android-sdk-macosx/platform-tools/
export PATH=${PATH}:/Volumes/WD1TExtensi/tools/android-sdk-macosx/tools/
export ANDROID_HOME=/Volumes/WD1TExtensi/tools/android-sdk-macosx/ 

配置完成后可以使用adb version来查看一下是否安装成功

3. 连接设备

手上测试的是一台小米Mix,小米的手机需要配置几个地方

  1. 连接上去之后USB选项配置“传输文件”
  2. 设置开发者模式,设置——我的设备——全部参数——MIUI版本(多次点击就可以开启)
  3. 设置开发者选项,设置——更多设置——开发者选项。打开USB调试、USB安装。关闭启用MIUI优化。

查看设备信息

system_profiler SPUSBDataType

创建adb_usb.ini文件,在文件中添加0x2717后保存退出

$ vi ~/.android/adb_usb.ini

重启adb

$ adb kill-server

$ adb start-server

$ adb devices

最后在devices里面可以看到设备连接表,如果这里返回空的说明配置有问题

到目录下运行程序

$ react-native run-android

遇到的问题

1. Could not determine java version from '10.0.1'[MAC OSX High Sierra]

这个是由于Java版本太新,而Gradle版本太老大致的

解决:首先 homebrew upgrade gradle 来更新mac上的版本,然后在修改配置

修改依赖的gradle版本 android/gradle/wrapper/gradle-wrapper.properties

#Wed Nov 23 12:42:37 AEDT 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip     //这里使用5.0版本是应为使用homebrew upgrade gradle之后update到的是gradle-5.0版本,保持同步

在代码文件的android/build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {  
    repositories {
        google()    //注意这个地方需要加上,否则会报错
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'   //这里的版本号需要和gradle文件的配置版本号匹配,否则无法加载。和上面的gradle-5.0匹配的是3.2.1版本,这个可以在官网上查到

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()   //注意这个地方需要加上,否则会报错
        mavenLocal()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
    }
}

gradle版本对应可以参考下图

具体参考了这几篇文章

ReactNative Mac配置安卓真机调试环境

添加google()配置

官网的Android SDK配置路径

在MacOSX中安装Android SDK

整理部分依赖不存在,需要安装extra中的Android Support Repository插件

2018/12/5 posted in  web

ReactNative入门

tutorial
https://reactnative.cn/docs/tutorial/

脚手架之一

基于react-native+redux搭建的P2P开源App
https://github.com/seawind8888/react-native-P2P

整理好了基本使用之后多了解几个脚手架,使用一个脚手架开始开发。

ECS6规范

查看运行的8081端口是否开启,如果开启了会报各种莫名的错误

lsof -n -i4TCP:8081
2018/12/3 posted in  web

Nativescript

2018/9/9 posted in  web

NodeJs

常见的Web框架包括:Express,Sails.js,koa,Meteor,DerbyJS,Total.js,restify……

ORM框架比Web框架要少一些:Sequelize,ORM2,Bookshelf.js,Objection.js……

模版引擎PK:Jade,EJS,Swig,Nunjucks,doT.js……

测试框架包括:Mocha,Expresso,Unit.js,Karma……

构建工具有:Grunt,Gulp,Webpack……

2017/9/3 posted in  web

javascript 笔记

javascript基本语法

1. 等号判断

要特别注意相等运算符==。JavaScript在设计时,有两种比较运算符:

第一种是==比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;

第二种是===比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。

由于JavaScript这个设计缺陷,不要使用比较,始终坚持使用=比较。

另一个例外是NaN这个特殊的Number与所有其他值都不相等,包括它自己:

NaN === NaN; // false

唯一能判断NaN的方法是通过isNaN()函数:

isNaN(NaN); // true

2. null和undefined

JavaScript的设计者希望用null表示一个空的值,而undefined表示值未定义。事实证明,这并没有什么卵用,区分两者的意义不大。大多数情况下,我们都应该用null。undefined仅仅在判断函数参数是否传递的情况下有用。

3. 数组

//数组方式1
[1, 2, 3.14, 'Hello', null, true];
//数组方式2
new Array(1, 2, 3); // 创建了数组[1, 2, 3]

4. 对象

JavaScript的对象是一组由键-值组成的无序集合,例如:

var person = {
    name: 'Bob',
    age: 20,
    tags: ['js', 'web', 'mobile'],
    city: 'Beijing',
    hasCar: true,
    zipcode: null
};

JavaScript对象的键都是字符串类型,值可以是任意数据类型。上述person对象一共定义了6个键值对,其中每个键又称为对象的属性,例如,person的name属性为'Bob',zipcode属性为null。

要获取一个对象的属性,我们用对象变量.属性名的方式:

person.name; // 'Bob'
person.zipcode; // null

5. strict 模式

JavaScript在设计之初,为了方便初学者学习,并不强制要求用var申明变量。这个设计错误带来了严重的后果:如果一个变量没有通过var申明就被使用,那么该变量就自动被申明为全局变量:

i = 10; // i现在是全局变量

在同一个页面的不同的JavaScript文件中,如果都不用var申明,恰好都使用了变量i,将造成变量i互相影响,产生难以调试的错误结果。

使用var申明的变量则不是全局变量,它的范围被限制在该变量被申明的函数体内(函数的概念将稍后讲解),同名变量在不同的函数体内互不冲突。

为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var申明变量,未使用var申明变量就使用的,将导致运行错误。

启用strict模式的方法是在JavaScript代码的第一行写上:

'use strict';

这是一个字符串,不支持strict模式的浏览器会把它当做一个字符串语句执行,支持strict模式的浏览器将开启strict模式运行JavaScript。

6. 字符串

  1. 多行字符串,使用
`这是一个
多行
字符串`;
  1. 模板字符串

如果有很多变量需要连接,用+号就比较麻烦。ES6新增了一种模板字符串,表示方法和上面的多行字符串一样,但是它会自动替换字符串中的变量:

var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;
alert(message);
  1. 操作字符串

var s = 'Hello, world!';
s.length; // 13

s[0]; // 'H'
s[6]; // ' '
s[7]; // 'w'
s[12]; // '!'
s[13]; // undefined 超出范围的索引不会报错,但一律返回undefined

//字符串不可以赋值,只可以读取
var s = 'Test';
s[0] = 'X';
alert(s); // s仍然为'Test'

var s = 'Hello';
s.toUpperCase(); // 返回'HELLO'

var s = 'Hello';
var lower = s.toLowerCase(); // 返回'hello'并赋值给变量lower
lower; // 'hello'

var s = 'hello, world';
s.indexOf('world'); // 返回7
s.indexOf('World'); // 没有找到指定的子串,返回-1

var s = 'hello, world'
s.substring(0, 5); // 从索引0开始到5(不包括5),返回'hello'
s.substring(7); // 从索引7开始到结束,返回'world'

  1. 数组

请注意,直接给Array的length赋一个新的值会导致Array大小的变化:

var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr变为[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; // arr变为[1, 2]

请注意,如果通过索引赋值时,索引超过了范围,同样会引起Array大小的变化:

var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']

大多数其他编程语言不允许直接改变数组的大小,越界访问索引会报错。然而,JavaScript的Array却不会有任何错误。在编写代码时,不建议直接修改Array的大小,访问索引时要确保索引不会越界。

一些函数的使用

indexOf() 搜索元素位置

slice() 对应String的substring的数组版本

push()向Array的末尾添加若干元素,pop()则把Array的最后一个元素删除掉

如果要往Array的头部添加若干元素,使用unshift()方法,shift()方法则把Array的第一个元素删掉

sort()可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序

reverse()把整个Array的元素给掉个个,也就是反转

splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素

concat()方法把当前的Array和另一个Array连接起来,并返回一个新的Array。请注意,concat()方法并没有修改当前Array,而是返回了一个新的Array。

join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串

  1. 对象
var xiaoming = {
    name: '小明',
    birth: 1990,
    school: 'No.1 Middle School',
    height: 1.70,
    weight: 65,
    score: null
};

JavaScript用一个{...}表示一个对象,键值对以xxx: xxx形式申明,用,隔开。注意,最后一个键值对不需要在末尾加,,如果加了,有的浏览器(如低版本的IE)将报错。

xiaohong的属性名middle-school不是一个有效的变量,就需要用''括起来。访问这个属性也无法使用.操作符,必须用['xxx']来访问:

xiaohong['middle-school']; // 'No.1 Middle School'
xiaohong['name']; // '小红'
xiaohong.name; // '小红'
//对象的属性可以采用点来访问,也可以采用中括号来访问,同时含特殊符号的属性只能使用中括号来访问

由于JavaScript的对象是动态类型,你可以自由地给一个对象添加或删除属性:

var xiaoming = {
    name: '小明'
};
xiaoming.age; // undefined
xiaoming.age = 18; // 新增一个age属性
xiaoming.age; // 18
delete xiaoming.age; // 删除age属性
xiaoming.age; // undefined
delete xiaoming['name']; // 删除name属性
xiaoming.name; // undefined
delete xiaoming.school; // 删除一个不存在的school属性也不会报错

如果我们要检测xiaoming是否拥有某一属性,可以用in操作符:

var xiaoming = {
    name: '小明',
    birth: 1990,
    school: 'No.1 Middle School',
    height: 1.70,
    weight: 65,
    score: null
};
'name' in xiaoming; // true
'grade' in xiaoming; // false

要判断一个属性是否是xiaoming自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法:

var xiaoming = {
    name: '小明'
};
xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false
  1. 判断

JavaScript把null、undefined、0、NaN和空字符串''视为false,其他值一概视为true,因此上述代码条件判断的结果是true。

  1. 循环
    for循环有个特别的地方

由于Array也是对象,而它的每个元素的索引被视为对象的属性,因此,for ... in循环可以直接循环出Array的索引:

var a = ['A', 'B', 'C'];
for (var i in a) {
    alert(i); // '0', '1', '2'
    alert(a[i]); // 'A', 'B', 'C'
      //注意for出来的不是对象,二是索引,这里是有区别的
}
  1. Map

如果用Map实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用JavaScript写一个Map如下:

var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95

初始化Map需要一个二维数组,或者直接初始化一个空Map。Map具有以下方法:

var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:

var m = new Map();
m.set('Adam', 67);
m.set('Adam', 88);
m.get('Adam'); // 88
  1. Set

要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set:

var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3

重复元素在Set中自动被过滤:

var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}

set可以通过add()和 delete()方法来添加和删除元素

  1. iteratble

遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。

具有iterable类型的集合可以通过新的for ... of循环来遍历。

for ... in循环由于历史遗留问题,它遍历的实际上是对象的属性名称。一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性。

当我们手动给Array对象添加了额外的属性后,for ... in循环将带来意想不到的意外效果:

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x in a) {
    alert(x); // '0', '1', '2', 'name'
}

for ... in循环将把name包括在内,但Array的length属性却不包括在内。

for ... of循环则完全修复了这些问题,它只循环集合本身的元素:

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x of a) {
    alert(x); // 'A', 'B', 'C'
}

然而,更好的方式是直接使用iterable内置的forEach方法,它接收一个函数,每次迭代就自动回调该函数。以Array为例:

//数组的回调是element,index,array
var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) {
    // element: 指向当前元素的值
    // index: 指向当前索引
    // array: 指向Array对象本身
    alert(element);
});

//Set的回调是element,sameElement,set
var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) {
    alert(element);
});

//Map 的回调是value,key,map
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) {
    alert(value);
});

函数

在JavaScript中,定义函数的方式如下:

function abs(x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}

//第二种函数定义方式,在这种方式下,function (x) { ... }是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs
var abs = function (x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
};

如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined。

由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:

abs(10, 'blablabla'); // 返回10
abs(-9, 'haha', 'hehe', null); // 返回9

传入的参数比定义的少也没有问题:

abs(); // 返回NaN

arguments

JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array:

function foo(x) {
    alert(x); // 10
    for (var i=0; i<arguments.length; i++) {
        alert(arguments[i]); // 10, 20, 30
    }
}

foo(10, 20, 30);

argument的可选参数问题

实际上arguments最常用于判断传入参数的个数。你可能会看到这样的写法:

// foo(a[, b], c)
// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a, b, c) {
    if (arguments.length === 2) {
        // 实际拿到的参数是a和b,c为undefined
        c = b; // 把b赋给c
        b = null; // b变为默认值
    }
    // ...
}

要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。

rest 参数

ES6标准引入了rest参数,上面的函数可以改写为:

function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
}

foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

foo(1);
// 结果:
// a = 1
// b = undefined
// Array []

变量和作用域

嵌套变量作用域

由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行:

'use strict';

function foo() {
    var x = 1;
    function bar() {
        var y = x + 1; // bar可以访问foo的变量x!
    }
    var z = y + 1; // ReferenceError! foo不可以访问bar的变量y!
}

变量提升

JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:

'use strict';

function foo() {
    var x = 'Hello, ' + y;
    alert(x);
    var y = 'Bob';
}

foo();

由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个var申明函数内部用到的所有变量:

function foo() {
    var
        x = 1, // x初始化为1
        y = x + 1, // y初始化为2
        z, i; // z和i为undefined
    // 其他语句:
    for (i=0; i<100; i++) {
        ...
    }
}

全局作用域

任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError错误。

局部作用域

由于JavaScript的变量作用域实际上是函数内部,我们在for循环等语句块中是无法定义具有局部作用域的变量的:

'use strict';

function foo() {
    for (var i=0; i<100; i++) {
        //
    }
    i += 100; // 仍然可以引用变量i
}

为了解决块级作用域,ES6引入了新的关键字let,用let替代var可以申明一个块级作用域的变量:

'use strict';

function foo() {
    var sum = 0;
    for (let i=0; i<100; i++) {
        sum += i;
    }
    i += 1; // SyntaxError
}

常量

常量

由于var和let申明的是变量,如果要申明一个常量,在ES6之前是不行的,我们通常用全部大写的变量来表示“这是一个常量,不要修改它的值”:

var PI = 3.14;

ES6标准引入了新的关键字const来定义常量,const与let都具有块级作用域:

'use strict';

const PI = 3.14;
PI = 3; // 某些浏览器不报错,但是无效果!
PI; // 3.14

方法

//对象的方法
var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        var y = new Date().getFullYear();
        return y - this.birth;
    }
};

xiaoming.age; // function xiaoming.age()
xiaoming.age(); // 今年调用是25,明年调用就变成26了

apply 方法

要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。

另一个与apply()类似的方法是call(),唯一区别是:

apply()把参数打包成Array再传入;

call()把参数按顺序传入。

javascript 装饰器

装饰器

利用apply(),我们还可以动态改变函数的行为。

JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数。

现在假定我们想统计一下代码一共调用了多少次parseInt(),可以把所有的调用都找出来,然后手动加上count += 1,不过这样做太傻了。最佳方案是用我们自己的函数替换掉默认的parseInt():

var count = 0;
var oldParseInt = parseInt; // 保存原函数

window.parseInt = function () {
    count += 1;
    return oldParseInt.apply(null, arguments); // 调用原函数
};

// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
count; // 3

高阶函数

JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

一个最简单的高阶函数:

function add(x, y, f) {
    return f(x) + f(y);
}

编写高阶函数,就是让函数的参数能够接收别的函数。

map/reduce

由于map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个新的Array作为结果:

function pow(x) {
    return x * x;
}

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]

Array的reduce()把一个函数作用在这个Array的[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

比方说对一个Array求和,就可以用reduce实现:

var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
    return x + y;
}); // 25

filter

Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。

例如,在一个Array中,删掉偶数,只保留奇数,可以这么写:

var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
    return x % 2 !== 0;
});
r; // [1, 5, 9, 15]

sort

sort()方法也是一个高阶函数,它还可以接收一个比较函数来实现自定义的排序。

要按数字大小排序,我们可以这么写:

var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return -1;
    }
    if (x > y) {
        return 1;
    }
    return 0;
}); // [1, 2, 10, 20]

sort()方法会直接对Array进行修改

闭包

典型的闭包

function lazy_sum(arr) {
    var sum = function () {
        return arr.reduce(function (x, y) {
            return x + y;
        });
    }
    return sum;
}
//当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:

var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
//调用函数f时,才真正计算求和的结果:

f(); // 15

箭头

generator

generator和函数不同的是,generator由function定义(注意多出的号),并且,除了return语句,还可以用yield返回多次。

标准对象

总结一下,有这么几条规则需要遵守:

  • 不要使用new Number()、new Boolean()、new String()创建包装对象;
  • 用parseInt()或parseFloat()来转换任意类型到number;
  • 用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;
  • 通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};
  • typeof操作符可以判断出number、boolean、string、function和undefined;
  • 判断Array要使用Array.isArray(arr);
  • 判断null请使用myVar === null;
  • 判断某个全局变量是否存在用typeof window.myVar === 'undefined';
  • 函数内部判断某个变量是否存在用typeof myVar === 'undefined'。
2017/8/19 posted in  web

前端需要整理学习的内容

内容梳理

  1. chrome 的控制台中console的使用方式,javascript的调试能力
2017/8/19 posted in  web

Strut on Node.js 入门

ubuntu下Node.js的npm环境安装

Node.js的安装

首先安装一些依赖包

sudo apt-get update
sudo apt-get install git-core curl build-essential openssl libssl-dev

首先我们先从github上将Node.js库克隆到本地:

git clone https://github.com/joyent/node.git
cd node

git tag # 这个命令将会显示Node的所有版本的列表
git checkout v0.10.33

然后可以编译和安装Node:

./configure
make
sudo make install

  安装完毕,我们就可以在命令行里面输入以下命令以便确认Node是否安装完毕:

node -v
v0.10.33

安装NPM

  这个很简单,NPM官方提供了安装NPM的脚本,所以我们把这个脚本下载下来执行一下就可以:

wget https://npmjs.org/install.sh --no-check-certificate
chmod 777 install.sh
./install.sh
npm -v
3.10.6

安装strut1

安装grunt版本 : npm install -g grunt-cli

拷贝 Struts : git clone git://github.com/tantaman/Strut.git

cd Strut

安装NPM依: npm install

运行Strut: grunt server (the server runs at localhost:9000)

这里安装strut1的时候,会报错,需要修改

17434 error notarget No compatible version found: phantomjs@'>=1.8.1 <1.9.0'
17434 error notarget Valid install targets:
17434 error notarget ["1.9.13","1.9.12","1.9.11","1.9.10","1.9.9","1.9.8","1.8.2-3","1.9.7-15","1.9.7-14","1.9.7-13","1.9.7-12","1.9.7-11","1.9.7-10","1.9.7-9","1.9.7-8","1.9.7-7","1.9.7-6","1.9.7-5","1.9.7-4","1.9.7-3","1.9.7-1","1.9.6-0","1.9.2-6","1.9.2-5","1.9.2-4","1.9.2-3","1.9.2-2","1.9.2-1","1.9.2-0","1.9.1-9","1.9.1-8","1.9.1-7","1.9.1-6","1.9.1-5","1.9.1-4","1.9.1-3","1.9.1-2","1.9.1-0","1.9.0-6","1.9.0-5","1.9.0-4","1.9.0-3","1.9.0-2","1.9.0-1","1.9.0-0","1.8.2-2","1.8.2-1","1.8.2-0","1.8.1-3","1.8.1-2","1.8.1-1","1.8.0-1","0.2.6","0.2.5","0.2.4","0.2.3","0.2.2","0.2.1","0.2.0","0.1.1","0.1.0","0.0.9","0.0.8","0.0.7","0.0.6","0.0.5","0.0.4","0.0.3","0.0.2","0.0.1"]

vi package.json

删除掉 "Grunt - mocha " : "~ 0.2.2"

2016/8/24 posted in  web

WebService的深度研究————Rest和Soap架构

SOAP和REST

典型的基于 SOAP 的 Web 服务以操作为中心,每个操作接受 XML 文档作为输入,提供 XML 文档作为输出。在本质上讲,它们是 RPC 风格的。而在遵循 REST 原则的 ROA 应用中,服务是以资源为中心的,对每个资源的操作都是标准化的 HTTP 方法。

SOAP

所有的SOAP消息发送都使用HTTP POST方法,并且所有SOAP消息的URI都是一样的。

SOAP(Simple Object Access Protocol )简单对象访问协议是在分散或分布式的环境中交换信息的简单的协议,是一个基于XML的协议,它包括四个部分:SOAP封装(envelop),封装定义了一个描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们的框架;SOAP编码规则(encoding rules),用于表示应用程序需要使用的数据类型的实例; SOAP RPC表示(RPC representation),表示远程过程调用和应答的协定;SOAP绑定(binding),使用底层协议交换信息。

SOAP的两个主要设计目标是简单性和可扩展性。

SOAP=RPC+HTTP+XML

SOAP简单的理解,就是这样的一个开放协议SOAP=RPC+HTTP+XML:采用HTTP作为底层通讯协议;RPC作为一致性的调用途径,XML作为数据传送的格式,允许服务提供者和服务客户经过防火墙在INTERNET进行通讯交互。
RPC的描叙可能不大准确,因为SOAP一开始构思就是要实现平台与环境的无关性和独立性,每一个通过网络的远程调用都可以通过SOAP封装起来,包括DCE(Distributed Computing Environment ) RPC CALLS,COM/DCOM CALLS, CORBA CALLS, JAVA CALLS,etc。

Rest

REST(Representational State Transfer)客户端应用程序随着每个资源表现状态的不同而发生状态转移。

可以使用遵循Rest设计原则的ROA(Resource-Oriented Architecture,面向资源的体系架构)进行设计。ROA是一种把实际问题转化为REST式的web服务的方法,它使得URI、HTTP、XML具有跟其他web应用一样的方式。

基本ROA步骤:

  • 分析应用需求中的数据集。
  • 映射数据集到 ROA 中的资源。
  • 对于每一资源,命名它的 URI。
  • 为每一资源设计其 Representations。
  • 用 hypermedia links 表述资源间的联系。

REST可以使用HTTP PUT、GET、DELETE等

四大基本设计原则
显式地使用 HTTP 方法

基于 REST 的 Web 服务的主要特征之一是以遵循 RFC 2616 定义的协议的方式显式使用 HTTP 方法。

REST 要求开发人员显式地使用 HTTP 方法,并且使用方式与协议定义一致。 这个基本 REST 设计原则建立了创建、读取、更新和删除(create, read, update, and delete,CRUD)操作与 HTTP 方法之间的一对一映射。

在实现上来可以使用get请求来实现add一条数据,或者使用post请求来查询,但这并不是优雅的REST设计。

无状态

REST Web 服务需要发送完整、独立的请求;也就是说,发送的请求包括所有需要满足的数据,以便中间服务器中的组件能够进行转发、路由和负载平衡,而不需要在请求之间在本地保存任何状态。

完整、独立的请求不要求服务器在处理请求时检索任何类型的应用程序上下文或状态。 REST Web 服务应用程序(或客户端)在 HTTP Header 和请求正文中包括服务器端组件生成响应所需要的所有参数、上下文和数据。 这种意义上的无状态可以改进 Web 服务性能,并简化服务器端组件的设计和实现,因为服务器上没有状态,从而消除了与外部应用程序同步会话数据的需要。

公开目录结构式的 URI

REST Web 服务 URI 的直观性应该达到很容易猜测的程度。 将 URI 看作是自身配备文档说明的接口,开发人员只需很少(如果有的话)的解释或参考资料即可了解它指向什么,并获得相关的资源。 为此,URI 的结构应该简单、可预测且易于理解。

在考虑基于 REST 的 Web 服务的 URI 结构时,需要指出的一些附加指导原则包括:

  • 隐藏服务器端脚本技术文件扩展名(.jsp、.php、.asp)——如果有的话,以便您能够移植到其他脚本技术而不用更改 URI。
  • 将所有内容保持小写。
  • 将空格替换为连字符或下划线(其中一种或另一种)。
  • 尽可能多地避免查询字符串。
  • 如果请求 URI 用于部分路径,与使用 404 Not Found 代码不同,应该始终提供缺省页面或资源作为响应。
  • URI 还应该是静态的,以便在资源发生更改或服务的实现发生更改时,链接保持不变。 这可以实现书签功能。 URI 中编码的资源之间的关系与在存储资源的位置表示资源关系的方式无关也是非常重要的。
传输 XML、JavaScript Object Notation (JSON),或同时传输这两者

基于 REST 的 Web 服务设计中的最后一组约束与应用程序和服务在请求/响应有效负载或 HTTP 正文中交换的数据的格式有关。 这是真正值得将一切保持简单、可读和连接在一起的方面。

为了赋予客户端请求最适合它们的特定内容类型的能力,您的服务的构造应该利用内置的 HTTP Accept Header,其中该 Header 的值为 MIME 类型。
基于 REST 的服务使用的常见 MIME 类型:

JSON application/json
XML application/xml
XHTML application/xhtml+xml

REST和SOAP的比较

接口抽象
  • RESTful Web服务使用标准的HTTP方法(GET_PUT_POST/DELETE) 来抽象所有 Web 系统的服务能力。
  • SOAP应用通过定义自己个性化的接口方法来抽象WEB服务。

标准化的RESTful Web服务带来了本身的一些HTTP的优势:

无状态性(stateless)

HTTP 协议从本质上说是一种无状态的协议,客户端发出的 HTTP 请求之间可以相互隔离,不存在相互的状态依赖。基于 HTTP 的 ROA,以非常自然的方式来实现无状态服务请求处理逻辑。对于分布式的应用而言,任意给定的两个服务请求 Request 1 与 Request 2, 由于它们之间并没有相互之间的状态依赖,就不需要对它们进行相互协作处理,其结果是:Request 1 与 Request 2 可以在任何的服务器上执行,这样的应用很容易在服务器端支持负载平衡 (load-balance)。

安全操作与幂指相等特性(Safety /Idempotence)

HTTP 的 GET、HEAD 请求本质上应该是安全的调用,即:GET、HEAD 调用不会有任何的副作用,不会造成服务器端状态的改变。对于服务器来说,客户端对某一 URI 做 n 次的 GET、HAED 调用,其状态与没有做调用是一样的,不会发生任何的改变。
HTTP 的 PUT、DELTE 调用,具有幂指相等特性 , 即:客户端对某一 URI 做 n 次的 PUT、DELTE 调用,其效果与做一次的调用是一样的。HTTP 的 GET、HEAD 方法也具有幂指相等特性。
HTTP 这些标准方法在原则上保证你的分布式系统具有这些特性,以帮助构建更加健壮的分布式系统。

安全控制

客户端发出的请求通过代理服务器(Proxy Server),代理服务器指定安全策略,对请求进行分发。由于REST类型可以直接看到URI,所以通过URI就可以判定相应的权限是否通过。
SOAP经过代理服务器时,无法通过URI直接看到相应的信息,必须要对SOAP进行解析才可以,所以需要第三方Proxy Server必须知晓当前的SOAP语义,这是造成了和Proxy Server之间的紧耦合。

缓存

REST可以充分利用HTTP协议对缓存的支持能力。HTTP 协议带条件的 HTTP GET 请求 (Conditional GET) 被设计用来节省客户端与服务器之间网络传输带来的开销,这也给客户端实现 Cache 机制 ( 包括在客户端与服务器之间的任何代理 ) 提供了可能。HTTP 协议通过 HTTP HEADER 域:If-Modified-Since_Last- Modified,If-None-Match_ETag 实现带条件的 GET 请求。
SOAP应用很难发挥HTTP本身的缓存能力。

连接性

在一个纯的 SOAP 应用中,URI 本质上除了用来指示 SOAP 服务器外,本身没有任何意义。
REST 可以通过 URI 驱动 SOAP 方法调用。

2016/1/18 posted in  web

jekyll 安装笔记

安装jekyll

在mac上安装 Command Line Tools for Xcode
完成之后执行

    williamtekiMacBook-Pro:valen_jekyll valentine$ sudo gem install jekyll
    Password:
    Fetching: liquid-2.6.1.gem (100%)
    Successfully installed liquid-2.6.1
    Fetching: fast-stemmer-1.0.2.gem (100%)
    Building native extensions.  This could take a while...
    Successfully installed fast-stemmer-1.0.2
    Fetching: classifier-1.3.4.gem (100%)
    Successfully installed classifier-1.3.4
    Fetching: kramdown-1.4.0.gem (100%)
    Successfully installed kramdown-1.4.0
    Fetching: yajl-ruby-1.1.0.gem (100%)
    Building native extensions.  This could take a while...
    Successfully installed yajl-ruby-1.1.0
    Fetching: posix-spawn-0.3.8.gem (100%)
    Building native extensions.  This could take a while...
    Successfully installed posix-spawn-0.3.8
    Fetching: pygments.rb-0.6.0.gem (100%)
    Successfully installed pygments.rb-0.6.0
    Fetching: mercenary-0.3.3.gem (100%)
    Successfully installed mercenary-0.3.3
    Fetching: safe_yaml-1.0.3.gem (100%)
    Successfully installed safe_yaml-1.0.3
    Fetching: colorator-0.1.gem (100%)
    Successfully installed colorator-0.1
    Fetching: redcarpet-3.1.2.gem (100%)
    Building native extensions.  This could take a while...
    Successfully installed redcarpet-3.1.2
    Fetching: blankslate-2.1.2.4.gem (100%)
    Successfully installed blankslate-2.1.2.4
    Fetching: parslet-1.5.0.gem (100%)
    Successfully installed parslet-1.5.0
    Fetching: toml-0.1.1.gem (100%)
    Successfully installed toml-0.1.1
    Fetching: jekyll-paginate-1.0.0.gem (100%)
    Successfully installed jekyll-paginate-1.0.0
    Fetching: jekyll-gist-1.1.0.gem (100%)
    Successfully installed jekyll-gist-1.1.0
    Fetching: coffee-script-source-1.7.0.gem (100%)
    Successfully installed coffee-script-source-1.7.0
    Fetching: execjs-2.2.1.gem (100%)
    Successfully installed execjs-2.2.1
    Fetching: coffee-script-2.2.0.gem (100%)
    Successfully installed coffee-script-2.2.0
    Fetching: jekyll-coffeescript-1.0.0.gem (100%)
    Successfully installed jekyll-coffeescript-1.0.0
    Fetching: sass-3.3.9.gem (100%)
    Successfully installed sass-3.3.9
    Fetching: jekyll-sass-converter-1.0.0.gem (100%)
    Successfully installed jekyll-sass-converter-1.0.0
    Fetching: timers-1.1.0.gem (100%)
    Successfully installed timers-1.1.0
    Fetching: celluloid-0.15.2.gem (100%)
    Successfully installed celluloid-0.15.2
    Fetching: rb-fsevent-0.9.4.gem (100%)
    Successfully installed rb-fsevent-0.9.4
    Fetching: ffi-1.9.3.gem (100%)
    Building native extensions.  This could take a while...
    Successfully installed ffi-1.9.3
    Fetching: rb-inotify-0.9.5.gem (100%)
    Successfully installed rb-inotify-0.9.5
    Fetching: listen-2.7.9.gem (100%)
    Successfully installed listen-2.7.9
    Fetching: jekyll-watch-1.0.0.gem (100%)
    Successfully installed jekyll-watch-1.0.0
    Fetching: jekyll-2.1.0.gem (100%)
    Successfully installed jekyll-2.1.0
    Parsing documentation for liquid-2.6.1
    Installing ri documentation for liquid-2.6.1
    Parsing documentation for fast-stemmer-1.0.2
    unable to convert "\xCA" from ASCII-8BIT to UTF-8 for lib/stemmer.bundle, skipping
    Installing ri documentation for fast-stemmer-1.0.2
    Parsing documentation for classifier-1.3.4
    Installing ri documentation for classifier-1.3.4
    Parsing documentation for kramdown-1.4.0
    Installing ri documentation for kramdown-1.4.0
    Parsing documentation for yajl-ruby-1.1.0
    unable to convert "\xCA" from ASCII-8BIT to UTF-8 for lib/yajl/yajl.bundle, skipping
    Installing ri documentation for yajl-ruby-1.1.0
    Parsing documentation for posix-spawn-0.3.8
    unable to convert "\xCA" from ASCII-8BIT to UTF-8 for lib/posix_spawn_ext.bundle, skipping
    Installing ri documentation for posix-spawn-0.3.8
    Parsing documentation for pygments.rb-0.6.0
    Installing ri documentation for pygments.rb-0.6.0
    Parsing documentation for mercenary-0.3.3
    Installing ri documentation for mercenary-0.3.3
    Parsing documentation for safe_yaml-1.0.3
    Installing ri documentation for safe_yaml-1.0.3
    Parsing documentation for colorator-0.1
    Installing ri documentation for colorator-0.1
    Parsing documentation for redcarpet-3.1.2
    unable to convert "\xCA" from ASCII-8BIT to UTF-8 for lib/redcarpet.bundle, skipping
    Installing ri documentation for redcarpet-3.1.2
    Parsing documentation for blankslate-2.1.2.4
    Installing ri documentation for blankslate-2.1.2.4
    Parsing documentation for parslet-1.5.0
    Installing ri documentation for parslet-1.5.0
    Parsing documentation for toml-0.1.1
    Installing ri documentation for toml-0.1.1
    Parsing documentation for jekyll-paginate-1.0.0
    Installing ri documentation for jekyll-paginate-1.0.0
    Parsing documentation for jekyll-gist-1.1.0
    Installing ri documentation for jekyll-gist-1.1.0
    Parsing documentation for coffee-script-source-1.7.0
    Installing ri documentation for coffee-script-source-1.7.0
    Parsing documentation for execjs-2.2.1
    Installing ri documentation for execjs-2.2.1
    Parsing documentation for coffee-script-2.2.0
    Installing ri documentation for coffee-script-2.2.0
    Parsing documentation for jekyll-coffeescript-1.0.0
    Installing ri documentation for jekyll-coffeescript-1.0.0
    Parsing documentation for sass-3.3.9
    Installing ri documentation for sass-3.3.9
    Parsing documentation for jekyll-sass-converter-1.0.0
    Installing ri documentation for jekyll-sass-converter-1.0.0
    Parsing documentation for timers-1.1.0
    Installing ri documentation for timers-1.1.0
    Parsing documentation for celluloid-0.15.2
    Installing ri documentation for celluloid-0.15.2
    Parsing documentation for rb-fsevent-0.9.4
    Installing ri documentation for rb-fsevent-0.9.4
    Parsing documentation for ffi-1.9.3
    Installing ri documentation for ffi-1.9.3
    Parsing documentation for rb-inotify-0.9.5
    Installing ri documentation for rb-inotify-0.9.5
    Parsing documentation for listen-2.7.9
    Installing ri documentation for listen-2.7.9
    Parsing documentation for jekyll-watch-1.0.0
    Installing ri documentation for jekyll-watch-1.0.0
    Parsing documentation for jekyll-2.1.0
    Installing ri documentation for jekyll-2.1.0
    30 gems installed       

gem会自动帮我们安装好所需的依赖包。这里可以看到安装jekyll的时候加载了哪些安装包

进入到jekyll 所需的目标文件夹中,执行对文件夹的编译

    $ jekyll build # => 当前文件夹中的内容将会生成到 ./site 文件夹中。
    $ jekyll build --destination <destination> # => 当前文件夹中的内容将会生成到目标文件夹<destination>中。 
    $ jekyll build --source <source> --destination <destination> # => 指定源文件夹<source>中的内容将会生成到目标文件夹<destinatio   n>中。 
    $ jekyll build --watch # => 当前文件夹中的内容将会生成到 ./site 文件夹中,# 查看改变,并 且   自动再生成。
    $ jekyll server
    # 启动jkelly服务器,服务器会启动在http://localhost:4000/
    $ jekyll server —detach
    # 在后台启动服务器,使用ps aux|grep jekyll  来查找相应的进程,使用kill命令关闭服务器。
    $ jekyll server —watch
    # 会查找变更并自动生成

载入一个模版

下载一个模版,放到相应文件夹,重新执行完毕之后,就可以发布新的模版了,修改这个模版。

2014/7/25 posted in  web