├── docs
├── .nojekyll
├── favicon.ico
├── _sidebar.md
├── AUTUMN.md
├── WINTER.md
├── SUMMER.md
├── MIXIN.md
├── index.html
├── SPRING.md
├── GUIDE.md
├── SECOND.md
├── FIRST.md
├── THIRD.md
├── demo.html
└── WHY.md
├── .babelrc
├── .travis.yml
├── .gitignore
├── src
├── interface
│ ├── coilConfig.ts
│ └── zcoilConig.ts
├── utils.ts
├── scoil.ts
├── serialize.ts
├── vue.ts
├── watch.ts
├── coil.ts
└── index.ts
├── test.js
├── tsconfig.json
├── demo
├── helloWorld.js
├── asyncData.js
├── $coil.js
└── in_vue.js
├── test-storage
├── index.html
├── test-vue.js
└── tests.js
├── index.html
├── package.json
├── webpack.config.js
├── README.md
├── test
└── zcoil-test.js
├── LICENSE
└── dist
└── zcoil.js
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/channg/zcoil/HEAD/docs/favicon.ico
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | language: node_js
3 | node_js:
4 | - "8"
5 | - "9"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | README.md.bak
3 | .idea/
4 | package-lock.json
5 | yarn-error.log
6 | src/test.ts
--------------------------------------------------------------------------------
/src/interface/coilConfig.ts:
--------------------------------------------------------------------------------
1 | export interface coilConif{
2 | rollback?:Boolean;
3 | errorContinue?:Boolean;
4 | saveWithExec?:Boolean;
5 | }
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | var z8 = new zcoil({});
2 | z8.init({
3 | data:{
4 | a:1
5 | }
6 | })
7 |
8 | z8.$watch((from,to)=>{
9 | debugger
10 | })
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/interface/zcoilConig.ts:
--------------------------------------------------------------------------------
1 | export interface zcoilConif{
2 | name?:String;
3 | localStorage?:boolean;
4 | deadline?:number;
5 | cover?:boolean;
6 | mixin?:any;
7 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist/",
4 | "sourceMap": true,
5 | "noImplicitAny": true,
6 | "module": "commonjs",
7 | "target": "es2015",
8 | "allowJs": true,
9 | "allowSyntheticDefaultImports":true
10 | }
11 | }
--------------------------------------------------------------------------------
/demo/helloWorld.js:
--------------------------------------------------------------------------------
1 | var z = new zcoil()
2 | z.init({
3 | data(){
4 | return {
5 | message: "hello world "
6 | }
7 | },
8 | name(yourName){
9 | this.message+=yourName
10 | }
11 | })
12 | z.name("channg")
13 |
14 | console.log(z.message)
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 | * **醉里挑灯看剑**
2 | * [为什么要创造这个库](WHY.md)
3 | * [前言](GUIDE.md)
4 | * [入门](FIRST.md)
5 | * [监听数据变化](SECOND.md)
6 | * [队列执行函数](THIRD.md)
7 | * **梦回吹角连营**
8 | * [浏览器存储](SPRING.md)
9 | * [合并实例对象](SUMMER.md)
10 | * [强制更新](AUTUMN.md)
11 | * **马作的卢飞快**
12 | * [与其他框架混用(vue)](MIXIN.md)
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | export function isPromise(obj:any) {
2 | return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
3 | }
4 |
5 | export function getTimestamp(){
6 | return new Date().getTime()
7 | }
8 |
9 | export function isFunction(functionToCheck:any) {
10 | return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
11 | }
--------------------------------------------------------------------------------
/demo/asyncData.js:
--------------------------------------------------------------------------------
1 | var z = new zcoil()
2 | z.init({
3 | data() {
4 | return {
5 | message: "hello world "
6 | }
7 | },
8 | asyncGetName() {
9 | return new Promise((resolve, reject) => {
10 | setTimeout(() => {
11 | resolve('channg')
12 | }, 2000)
13 | })
14 | },
15 | name() {
16 | this.asyncGetName().then((name) => {
17 | this.message += name
18 | })
19 | }
20 | })
21 |
22 | z.name()
23 | z.$watch((from,to)=>{
24 | debugger
25 | })
--------------------------------------------------------------------------------
/src/scoil.ts:
--------------------------------------------------------------------------------
1 | import forIn = require('lodash/forIn')
2 | import has = require( 'lodash/has')
3 | export default class scoil {
4 | model: any = {};
5 | constructor(_model: any, zcoil: any, data: any) {
6 | forIn(_model, (value, key) => {
7 | if (has(data, key)) {
8 | this.model[key] = data[key]
9 | } else {
10 | this.model[key] = value
11 | }
12 | })
13 | this.model['_call'] = zcoil._call
14 | this.model.$zcoil = zcoil
15 | };
16 | }
--------------------------------------------------------------------------------
/docs/AUTUMN.md:
--------------------------------------------------------------------------------
1 | # 追究
2 |
3 | 如果一个数据在方法运行外部被改变,`zcoil`应该如何得知呢?
4 |
5 | `zcoil`没有使用`definePrototype`,所有当数据在方法外部被改变的时候,`zcoil`也就无法知晓,从而产生`$watch`无法得知数据变动的后果。
6 |
7 | ```
8 | var z = new zcoil()
9 | z.init({
10 | data(){
11 | return {
12 | message: "hello world "
13 | }
14 | }
15 | })
16 | z.messsage="abc" //不会触发$watch
17 | ```
18 |
19 | 如果我们必须要在程序外部使用数据并进行赋值操作,我们必须要主动通知。
20 |
21 | 使用`z.$commit()`主动通知程序。
22 |
23 | ```
24 | var z = new zcoil()
25 | z.init({
26 | data(){
27 | return {
28 | message: "hello world "
29 | }
30 | }
31 | })
32 | z.messsage="abc" //不会触发$watch
33 | z.$commit()
34 | ```
35 | 调用了`$commit()`之后,`$watch`便可以得知数据的状态是否被更新了。
--------------------------------------------------------------------------------
/docs/WINTER.md:
--------------------------------------------------------------------------------
1 | # 寒冬
2 |
3 | 很高兴,你能看到这里。
4 |
5 | 但是接下来我只想说一些废话,吐槽一下。
6 |
7 | ---
8 |
9 | 冬至来了,春天还会远吗。
10 |
11 | 还是很远,有很多人,并不能熬过这个冬天。
12 |
13 | 从这个框架初到至今,一个月都在反复的琢磨,疲惫、焦虑、遇到困难的时候,并没有一个人能交流,焦头烂额的时候只能自己抓头发。
14 |
15 | 但那时候还是**春天**,每解决一个问题,就到了花开的时候,芳香四溢。
16 |
17 | 那时候我相信,我的作品可以帮助很多人解决问题,或者通过我的源代码学习到一点点新的知识,我就心满意足了。因为这就是**开源**的力量
18 |
19 | 直到现在,我想寻求一些伙伴,或者说推广一下我这一个月的努力成果的时候。**冬天**来了。
20 |
21 | 我遇到了很多人,向他们展示我的成果。而他们不会看一眼你的努力,却以挑刺为彰显自己能力的手段;被讽刺,被嘲笑,我只能默不作声。
22 |
23 | 因为没有**成绩**
24 |
25 | 我不想向他们去解释,这可能我内心还是有自己的骄傲。
26 |
27 | star = 1 1 = `我`
28 |
29 | 我不在意 star 的数量,我只想得到一些客观的评价。
30 |
31 | ---
32 |
33 | 如果你看过`zocil`的使用方法,应该发现和`vue`相同,将数据集成在了内部。
34 |
35 | 当然这很不利于在现有项目中使用。
36 |
37 | 我还是这么设计了。
38 |
39 | 原因呢?
40 |
41 | `人总要有理想的不是吗`,未来我会自己去实现`view`层。
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/serialize.ts:
--------------------------------------------------------------------------------
1 | import {setItem,getItem,removeItem} from 'localforage'
2 | import {getTimestamp} from './utils'
3 |
4 | export function serializeData(id:string,data:any){
5 | return setItem(id,data)
6 | }
7 |
8 | export function getData(id:string){
9 | return new Promise((resolve,reject)=>{
10 | getItem(`_${id}_deadline`).then((time:number)=>{
11 | if(time&&time>getTimestamp()){
12 | getItem(id).then((data)=>{
13 | resolve(data)
14 | }).catch(()=>{
15 | resolve()
16 | })
17 | }else{
18 | resolve()
19 | removeItem(id)
20 | removeItem(`_${id}_deadline`)
21 | }
22 | })
23 | })
24 | }
--------------------------------------------------------------------------------
/demo/$coil.js:
--------------------------------------------------------------------------------
1 | var z = new zcoil()
2 | z.init({
3 | data() {
4 | return {
5 | message: "hello world "
6 | }
7 | },
8 | asyncGetSaySomething(param) {
9 | return new Promise((resolve, reject) => {
10 | setTimeout(() => {
11 | resolve(param)
12 | }, 1000)
13 | })
14 | },
15 | say(param) {
16 | this.asyncGetSaySomething(param).then((say) => {
17 | this.message += "," + say
18 | })
19 | },
20 | endToSay(){
21 | this.message += ",come on "
22 | }
23 | })
24 |
25 | z.$watch((from,to)=>{
26 | console.log(from.message)
27 | console.log(to.message)
28 | })
29 |
30 |
31 | var hl = z.$coil().say("Thank your star this project")
32 |
33 | hl = hl.endToSay()
34 |
35 | hl = hl.say("It works really well")
36 |
37 | hl.exec((data)=>{
38 | debugger
39 | })
40 |
41 |
--------------------------------------------------------------------------------
/docs/SUMMER.md:
--------------------------------------------------------------------------------
1 | # 穿针引线
2 |
3 | `zcoil`提供了一个方法,用于合并两个`zocil`实例对象。
4 |
5 | ```javascript
6 | var z3 = new zcoil()
7 | z3.init({
8 | data() {
9 | return {
10 | index: 2,
11 | type:'last'
12 | }
13 | },
14 | assignment() {
15 | this.index = 200
16 | }
17 | }
18 | )
19 |
20 | var z4 = new zcoil()
21 | z4.init({
22 | data() {
23 | return {
24 | index: 4
25 | }
26 | },
27 | assignment() {
28 | this.index = 300
29 | }
30 | }
31 | )
32 | ```
33 |
34 | 使用`zcoil.$assign(z3,z4)`
35 |
36 | ```
37 | var zassign = zcoil.$assign(z3,z4)
38 | ```
39 | 前者相同的方法,属性,将会被后者覆盖。
40 |
41 | ```javascript
42 | zassign.index // 4
43 | zassign.assignment()
44 | zassign.index //300
45 | ```
46 | >**tips**
47 | >
48 | >`zcoil.$assign` 相当于新生成了一个zcoli实例对象,之前的对象如果发生改变,生成的对象不会同步改变。
49 |
50 |
--------------------------------------------------------------------------------
/docs/MIXIN.md:
--------------------------------------------------------------------------------
1 | # 与其他框架混用
2 |
3 | 当我们并不需要将数据存储在`zcoil`中时。我们可以不去传入`data方法`。我们需要在`new zcoil`传入我们存储数据的变量。
4 |
5 | ```javascript
6 | new zcoil({
7 | mixin:xxx
8 | })
9 | ```
10 |
11 | 这样我们就能在程序中 使用`this.$mixin`去获取传入的数据用于赋值操作了。
12 |
13 | ## 与vue混用
14 |
15 | `zcoil`实例本身就是一个vue插件
16 | ```javascript
17 | var z = new zcoil()
18 | z.init(...)
19 | ```
20 | 当实例话了一个`zcoil`对象之后,直接可以使用
21 | ```
22 | Vue.use(z)
23 | ```
24 |
25 | 这时候,在你的vue组件中的就可以使用`this.$zcoil`获取你使用`Vue.use(z)`的`z`变量。
26 |
27 | 这时候,你可以在`created`中使用
28 | ```
29 | created(){
30 | this.$zcoil.$invoke(this)
31 | }
32 | ```
33 | 这个方法是将`z`内部属性名与`this`相同的变量同步到`this`中。
34 | ```javascript
35 | z.init({
36 | data:{
37 | message:10
38 | }
39 | })
40 |
41 | new Vue({
42 | data(){
43 | reuturn {
44 | message:0
45 | }
46 | },
47 | created(){
48 | this.$zcoil.$invoke(this)
49 | //这时候 this.message的值将会变为10
50 | }
51 | })
52 | ```
53 |
54 | 接下来你就可以在`vue`中使用`zcoil`了
55 |
--------------------------------------------------------------------------------
/demo/in_vue.js:
--------------------------------------------------------------------------------
1 | var z = new zcoil()
2 | z.init({
3 | data() {
4 | return {
5 | message: "hello world "
6 | }
7 | },
8 | asyncGetName() {
9 | return new Promise((resolve, reject) => {
10 | setTimeout(() => {
11 | resolve('my friend')
12 | }, 200)
13 | })
14 | },
15 | asyncGetSaySomething(param) {
16 | return new Promise((resolve, reject) => {
17 | setTimeout(() => {
18 | resolve(param)
19 | }, 100)
20 | })
21 | },
22 | name() {
23 | this.asyncGetName().then((name) => {
24 | this.message += name
25 | })
26 | },
27 | say(param) {
28 | this.asyncGetSaySomething(param).then((say) => {
29 | this.message += "," + say
30 | })
31 | }
32 | })
33 |
34 | Vue.use(z)
35 | var vm = new Vue({
36 | el:"#vm",
37 | data(){
38 | return{
39 | z:this.$zcoil,
40 | message:""
41 | }
42 | },
43 | store:z,
44 | created(){
45 | this.z.$invoke(this)
46 | this.z.$coil().say("enjoy this ,").name().exec()
47 | }
48 | })
--------------------------------------------------------------------------------
/test-storage/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mocha
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/vue.ts:
--------------------------------------------------------------------------------
1 | import forIn = require('lodash/forIn');
2 | /**
3 | * vue install function
4 | * @param Vue
5 | * @param options
6 | */
7 | export function install(Vue:any, options:any) {
8 | Vue.prototype.$zcoil = this
9 | /**
10 | * $use to watch the data and save in vm
11 | * @param vm
12 | * @param options
13 | */
14 | this.$invoke = (vm:any, options:any)=> {
15 | this.$watch((from:any, to:any)=> {
16 | if (!!options) {
17 | if(Array.isArray(options)){
18 | options.forEach((key)=>{
19 | vm[key] = to[key]
20 | })
21 | }else{
22 | forIn(options,(value:any,key:any)=>{
23 | vm[key] = to[value]
24 | })
25 | }
26 | }else{
27 | forIn(to, (value:any, key:any)=> {
28 | if (vm[key] !== undefined) {
29 | vm[key] = value
30 | }
31 | })
32 | }
33 | })
34 | }
35 | }
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | zcoil
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Getting Started
4 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/docs/SPRING.md:
--------------------------------------------------------------------------------
1 | # 更多
2 |
3 | `zcoil`内集成了浏览器数据存储,可以快捷的将`data`存入浏览器中。
4 |
5 | ```javascript
6 | new zcoil({
7 | name:"channg",
8 | localStorage:true
9 | })
10 | ```
11 |
12 | 初始化`zcoil`时,传入的对象含有`name`和`localStorage:true`属性。当`data`内的数据被更新时,会被同步到浏览器的存储中。
13 |
14 | >zcoil 中浏览器存储使用的 localForage ,由于 localForage 机制原因, 存储为异步函数,所以不能保证数据被更新时,立刻能被存储到浏览器中。
15 |
16 | ### 获取
17 |
18 | 存储在浏览器的数据 可以使用 `new zcoil().$deserialize()`方法同步到`data`中。
19 |
20 | 如果你并不想使用`zcoil`自动同步数据,加入`cover:false`,`$deserialize()`被调用的时候不会自动同步数据,需要手动注入方法同步
21 | ```javascript
22 | var z = new zcoil({
23 | name:"channg",
24 | localStorage:true,
25 | cover:false
26 | })
27 | z.init({
28 | data(){
29 | ...
30 | },
31 | some(){
32 | this.$deserialize((data)=>{
33 | this.some = data.some
34 | ....
35 | })
36 | }
37 | })
38 | ```
39 |
40 | ### 进阶
41 |
42 | 使用`$coil`链式同步
43 |
44 | ```javascript
45 | var coil = z.$coil().$deserialize()
46 |
47 | coil.dosomething()
48 | ```
49 |
50 | 使用`$coil`调用`$deserialize`之后,剩下的所有方法都会在同步数据之后被执行,非常简单易用。
51 |
52 |
53 | ### 超时时间
54 |
55 | ```javascript
56 | var z = new zcoil({
57 | name:"channg",
58 | localStorage:true,
59 | cover:false
60 | deadline:60 * 60 *24
61 | })
62 | ```
63 |
64 | `deadline` 是有效时间,单位为秒,超时后同步数据将失效。默认` deadline: 30 * 24 * 3600`
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/docs/GUIDE.md:
--------------------------------------------------------------------------------
1 | # 楔子
2 |
3 | 任何事物的诞生都有理由,一个框架也是。
4 |
5 | `zcoil`的诞生,便是为了解决更复杂的数据操作场景的一个`model`层框架。当程序中数据获取、更新的方式随着产品迭代逐步提升时,对阅读代码,以及增加需求的时间成本会高度增加。
6 |
7 | `zcoil`的初衷便是为了解决如何在复杂数据交互场景下进行`更快捷、优雅`生产出更优美、直观的code,并含有许多很酷的api。
8 |
9 | ## 为什么使用
10 | 使用`zocil` 可以生成多个,方法的消息队列,当你的数据发生异步请求时,你不需要再等待数据返回再执行下一个方法。直接可以按照顺序的将他们塞入消息队列中,方法的消息队列将顺序的消费他们。
11 | 举个例子,一个点击事件会发出一个请求,但依赖于初始化的时候去请求`userinfo`,这时候你只需要在初始化的时候创建消息队列,init的时候塞入请求`userinfo`的方法,接下来的点击事件,你不需要关心`userinfo`是否完成,只需要继续向消息队列塞入方法。
12 |
13 | 使用`zocil`可以使用高性能的`$watch`,`zocil`的`$watch`模型,基于`AOP`,完全基于用户行为,不会消耗任何性能。
14 |
15 | 使用`zocil`可以超级快速的将数据存入本地浏览器内,内置了`localforage`兼容包括ie8及以上的现代浏览器,可以在第二次进入页面的时候快速取出数据。
16 |
17 | `zocil`也是一个很好入手去实践的框架,学习`zcoil`你可以理解框架的原理。在创作的时候,我遇到了很多包括:`this`指向;`浅复制`;`深复制`的问题。
18 | 在框架搭建过程中,也解决了很多问题:`lodash`按需加载;`travis ci `配合`chrome headless`与`mocha`自动化测试;`webpack`导出实例。
19 | 学习一个框架确实收获很多。
20 |
21 | ## 前言
22 | 使用zcoil的时候,你可能需要知晓的知识点
23 |
24 | ### Promise
25 |
26 | 使用**new Promise()**创建一个`Promise`对象Promise
27 | ```
28 | new Promise( function(resolve, reject) {...} /* executor */ );
29 | ```
30 |
31 | ### EventLoop
32 |
33 | JavaScript 的并发模型基于"事件循环"。这个模型与像 C 或者 Java 这种其它语言中的模型截然不同。
34 |
35 | ## 接下来
36 | 那么,我们可以开始新的旅程了。
37 | ```
38 | npm install zcoil
39 | ```
40 | ## [ -> 入门 <-](FIRST.md)
41 |
--------------------------------------------------------------------------------
/src/watch.ts:
--------------------------------------------------------------------------------
1 | import isEqual =require('lodash/isEqual');
2 | import cloneDeep =require('lodash/cloneDeep');
3 | import get = require( 'lodash/get')
4 |
5 | /**
6 | * watch 每调用一次$watch 就会初始化一个 watch 对象i
7 | */
8 | export class watch {
9 | _expression: string;
10 | _expression_is_array: Boolean
11 | _init_data: any
12 | _callback: Function
13 |
14 | _on_data_change(to: any) {
15 | // expression 为string
16 | if (this._expression && !this._expression_is_array) {
17 | var isEq = this._expressionEquals(this._expression, to, this._init_data)
18 | if (!isEq) {
19 | this._callback(get(this._init_data, this._expression), get(to, this._expression))
20 | this._init_data = cloneDeep(to)
21 | }
22 | } else {
23 | if (!isEqual(to, this._init_data)) {
24 | let deep_to = cloneDeep(to)
25 | this._callback(this._init_data, deep_to)
26 | this._init_data = deep_to
27 | }
28 | }
29 | }
30 |
31 | _expressionEquals(expression: any, to: any, from: any) {
32 | return isEqual(get(to, expression), get(from, expression))
33 | }
34 |
35 | constructor(expression: any, callback: Function, _data: any) {
36 | this._callback = callback
37 | this._init_data = _data
38 | if (typeof expression == 'string') {
39 | this._expression = expression
40 | this._expression_is_array = false
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/docs/SECOND.md:
--------------------------------------------------------------------------------
1 | # 窥镜
2 |
3 | 对于一个数据的改变,我们可能有几种方式得知呢?
4 | * 当一个数据更新的时候。
5 | * 当数据有可能发生改变的时候进行判断。
6 | * 定时获取数据状态,定时判断。
7 |
8 | `zcoil`使用的是第二种,在数据有可能发生改变的时候进行判断。下面将要介绍,如何在`zcoil`中获取数据改变的时机。
9 |
10 | ## $watch
11 | >使用$watch来监听数据的变化。
12 |
13 | `z.$watch(param?,callback)`
14 | params:`String` 需要监听数据的key,若不填,将检测所有数据变化。
15 | callback:`Function`回调函数,返回参数携带`from`,`to`为数据变化前与数据变化后的值,若填写了`param`,将会针对性的返回`from`与`to`,不会讲整个数据全部返回。
16 |
17 |
18 |
19 | ### example
20 | ```javascript
21 | var z = new zcoil()
22 | z.init({
23 | data() {
24 | return {
25 | message: "hello world "
26 | }
27 | },
28 | asyncGetName() {
29 | return new Promise((resolve, reject) => {
30 | setTimeout(() => {
31 | resolve('channg')
32 | }, 2000)
33 | })
34 | },
35 | name() {
36 | this.asyncGetName().then((name) => {
37 | this.message += name
38 | })
39 | }
40 | })
41 | z.$watch((from,to)=>{
42 | from.message //hello world
43 | to.message //hello world channg
44 | })
45 |
46 | z.$watch('message',(from,to)=>{
47 | from //hello world
48 | to //hello world channg
49 | })
50 |
51 | z.name()
52 | ```
53 |
54 | ## 探索
55 |
56 | `$watch` 是如何做到检测数据变动的呢?
57 |
58 | 在`zcoil`中,所有方法都会在执行前执行后被标记。对于`async**`方法,会提前解析返回的`promise`,同样在执行前后进行标记,并返回一个新的被包装的`promise`对象。
59 |
60 | 很显然`$watch`是惰性的,只有当特定条件下被触发的时候才会被执行。也正是这一点,使得它性能相当优越,可以作为常规性手段进行使用。
61 |
62 | 也正是使用了这种惰性检测的方法,使得`zcoil`的拥有更好的兼容性,因为不依赖于ES5的`Object.defineProperty()`。
63 |
64 | ### 接下来
65 |
66 | `$watch`只是`zocil`中最普通的武器,接下来你讲面对的是`zcoil`的杀手锏。
67 |
68 |
69 | ## [ -> 队列执行函数 <-](THIRD.md)
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zcoil",
3 | "version": "0.0.5",
4 | "description": "zcoil",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "webpack --mode development",
8 | "build": "cross-env webpack --mode production && mocha",
9 | "server": "webpack-dev-server --mode development --port 8088",
10 | "serve": "cross-env npm run opn && npm run server",
11 | "testnode": "mocha",
12 | "test": "cross-env npm run testnode && npm run teststorage",
13 | "opn": "opn http://localhost:8088/",
14 | "teststorage": "mocha-chrome ./test-storage/index.html",
15 | "doc": "docsify serve ./docs"
16 | },
17 | "keywords": [
18 | "webpack"
19 | ],
20 | "repository": "https://github.com/channg/zcoil",
21 | "author": "channg",
22 | "license": "MIT",
23 | "devDependencies": {
24 | "@types/jquery": "^3.3.0",
25 | "@types/lodash": "^4.14.109",
26 | "babel-loader": "^7.1.4",
27 | "babel-plugin-lodash": "^3.3.4",
28 | "babel-preset-es2015": "^6.24.1",
29 | "cross-env": "^5.2.0",
30 | "css-loader": "^0.28.10",
31 | "less": "^3.0.1",
32 | "less-loader": "^4.0.6",
33 | "lodash-webpack-plugin": "^0.11.5",
34 | "mocha": "^5.2.0",
35 | "mocha-chrome": "^1.1.0",
36 | "opn-cli": "^3.1.0",
37 | "style-loader": "^0.20.2",
38 | "ts-loader": "^4.0.1",
39 | "typescript": "^2.7.2",
40 | "uglifyjs-webpack-plugin": "^1.2.6",
41 | "webpack": "^4.0.1",
42 | "webpack-cli": "^2.0.4",
43 | "webpack-dev-server": "^3.1.0"
44 | },
45 | "dependencies": {
46 | "localforage": "^1.7.2",
47 | "lodash": "^4.17.10"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/test-storage/test-vue.js:
--------------------------------------------------------------------------------
1 | var expect = chai.expect;
2 |
3 | var z = new zcoil()
4 | z.init({
5 | data() {
6 | return {
7 | message: "hello world "
8 | }
9 | },
10 | asyncGetName() {
11 | return new Promise((resolve, reject) => {
12 | setTimeout(() => {
13 | resolve('my friend')
14 | }, 100)
15 | })
16 | },
17 | asyncGetSaySomething(param) {
18 | return new Promise((resolve, reject) => {
19 | setTimeout(() => {
20 | resolve(param)
21 | }, 200)
22 | })
23 | },
24 | name() {
25 | this.asyncGetName().then((name) => {
26 | this.message += name
27 | })
28 | },
29 | say(param) {
30 | this.asyncGetSaySomething(param).then((say) => {
31 | this.message += "," + say
32 | })
33 | }
34 | })
35 | Vue.use(z)
36 | describe('zcoil with vue', function() {
37 | it('vue use $coil', function(done) {
38 | var vm = new Vue({
39 | el:"#vm",
40 | data(){
41 | return{
42 | z:this.$zcoil,
43 | message:""
44 | }
45 | },
46 | watch:{
47 | message(some){
48 | if(some==='hello world ,enjoy this ,'){
49 | expect(z.message).to.be.equal(this.message);
50 |
51 | }
52 | if(some==='hello world ,enjoy this ,my friend'){
53 | expect(z.message).to.be.equal(this.message);
54 | done()
55 | }
56 | }
57 | },
58 | store:z,
59 | created(){
60 | this.z.$invoke(this)
61 | this.z.$coil().say("enjoy this ,").name().exec()
62 | }
63 | })
64 | });
65 | })
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
2 | const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
3 | module.exports = (env, argv) => {
4 | const config = {
5 | entry: {
6 | zcoil: "./src/index.ts"
7 | },
8 |
9 | module: {
10 | rules: [{
11 | test: /\.less$/,
12 | use: [{
13 | loader: "style-loader" // creates style nodes from JS strings
14 | }, {
15 | loader: "css-loader" // translates CSS into CommonJS
16 | }, {
17 | loader: "less-loader" // compiles Less to CSS
18 | }]
19 | }, {
20 | test: /\.tsx?$/,
21 | use: [
22 | {
23 | loader: 'babel-loader',
24 | options: {
25 | plugins: ['lodash']
26 | }
27 | }, {
28 | loader: 'ts-loader'
29 | }],
30 | exclude: /node_modules/,
31 | }
32 | ]
33 | },
34 | optimization: {
35 | splitChunks: {}
36 | },
37 | resolve: {
38 | extensions: ['.tsx', '.ts', '.js']
39 | },
40 | output: {
41 | globalObject: 'this',
42 | libraryTarget: 'umd',
43 | library: "zcoil",
44 | filename: "[name].js",
45 | libraryExport: 'default'
46 | },
47 | plugins: [
48 | new LodashModuleReplacementPlugin,
49 | ]
50 | }
51 | if (argv.mode === 'development') {
52 | config.devtool = 'inline-source-map'
53 | } else {
54 | config.plugins = [
55 | new UglifyJsPlugin({
56 | uglifyOptions: {
57 | compress: {
58 | warnings: false
59 | },
60 | output: {
61 | comments: false
62 | }
63 | }
64 | })
65 | ]
66 | }
67 | return config
68 | }
--------------------------------------------------------------------------------
/docs/FIRST.md:
--------------------------------------------------------------------------------
1 | # 入门
2 |
3 | ## 引入
4 |
5 |
6 | ```
7 | import zcoil from 'zcoil'
8 | ```
9 | `or`
10 |
11 | ```
12 | var zocil = require('zocil')
13 | ```
14 | `or`
15 |
16 | **直接引用dist目录下的 zcoil.js文件**
17 |
18 | ## 初始化
19 |
20 | 使用new 创建一个zcoil实例对象,并调用init 方法 进行初始化
21 |
22 | ```javascript
23 | var z = new zcoil()
24 | z.init({
25 | data(){
26 | return {
27 | message: "hello world"
28 | }
29 | }
30 | })
31 | ```
32 | 使用`init`方法对实例化的zocil对象进行初始化,`init`方法有且只有一个参数,一个包含着函数键值对的对象。
33 | 这个对象必须有一个`data`方法,并`return`了初始化时的参数。
34 |
35 | 当我们完成了这些,我们就可以开始使用`zcoil`了。
36 | ```
37 | z.message //hello world
38 | ```
39 |
40 | ## 尝试
41 |
42 | `init`方法参数对象中,可以添加更多方法,并可以直接调用。
43 | ```javascript
44 | var z = new zcoil()
45 | z.init({
46 | data(){
47 | return {
48 | message: "hello world "
49 | }
50 | },
51 | name(yourName){
52 | this.message+=yourName
53 | }
54 | })
55 |
56 | z.name("channg")
57 | console.log(z.message) //hello world channg
58 | ```
59 | 看起来是不是很不错,你可以将所有数据操作全部作为方法来调用,语义化的方法名,可以更好的让人理解程序。
60 |
61 | ## 异步数据
62 |
63 | 在zcoil中使用异步,需要多一个步骤。
64 |
65 | ```javascript
66 | var z = new zcoil()
67 | z.init({
68 | data() {
69 | return {
70 | message: "hello world "
71 | }
72 | },
73 | asyncGetName() {
74 | return new Promise((resolve, reject) => {
75 | setTimeout(() => {
76 | resolve('channg')
77 | }, 2000)
78 | })
79 | },
80 | name() {
81 | this.asyncGetName().then((name) => {
82 | this.message += name
83 | })
84 | }
85 | })
86 |
87 | z.name()
88 | ```
89 | `asyncGetName` 是一个返回Promise的异步方法。`asyncGetName`返回的Promise对象,在`name`方法中被执行,改变了`message`的值,两者只有调用关系,互相没有交集,从而做到数据隔离,
90 |
91 | 但是这样会有一个问题。
92 | `z.name()`被调用的时候,`message`的值并没有发生改变,那么我们需要在什么时候获取更新后的message的值呢。
93 |
94 | 当然,我们需要下回分解。
95 |
96 | ## [ -> 监听数据变化 <-](SECOND.md)
97 |
98 |
--------------------------------------------------------------------------------
/test-storage/tests.js:
--------------------------------------------------------------------------------
1 | var expect = chai.expect;
2 |
3 |
4 |
5 |
6 | var z6 = new zcoil({
7 | name:"test01",
8 | localStorage:true
9 | })
10 | z6.init({
11 | data() {
12 | return {
13 | index: 4
14 | }
15 | },
16 | assignment() {
17 | this.index = 300
18 | }
19 | }
20 | )
21 | z6.assignment()
22 | describe('zcoil serialize', function() {
23 | it('The value is correct when not serialized.', function() {
24 | expect(z6.index).to.be.equal(300);
25 | });
26 | it('Check the value after serialization(Will succeed on the second).', function(done) {
27 | localforage.setItem('test01',{index:400}).then(()=>{
28 | localforage.setItem('_test01_deadline',new Date().getTime()+1000000).then(()=>{
29 | z6.$deserialize().then((data)=>{
30 | expect(z6.index).to.be.equal(400);
31 | expect(data.index).to.be.equal(400);
32 | done()
33 | })
34 | })
35 | })
36 | });
37 | it('Test zcoil in vue with $mixin.', function(done) {
38 | var vm = new Vue({
39 | data() {
40 | return {
41 | z: {},
42 | coil: {},
43 | message: "hello world ",
44 | }
45 | },
46 | created() {
47 | this.z = new zcoil({
48 | mixin:this
49 | })
50 | this.z.init({
51 | asyncGetSaySomething(param) {
52 | return new Promise((resolve, reject) => {
53 | setTimeout(() => {
54 | resolve(param)
55 | }, 200)
56 | })
57 | },
58 | say(param) {
59 | this.asyncGetSaySomething(param).then((say) => {
60 | this.$mixin.message += "," + say
61 | })
62 | },
63 | endToSay() {
64 | this.$mixin.message += ",come on "
65 | }
66 | })
67 | },
68 | methods: {
69 | dosome() {
70 | this.coil = this.z.$coil().say("lll")
71 | this.coil = this.coil.endToSay()
72 | this.coil = this.coil.say("It works really well")
73 | this.coil = this.coil.exec((data)=>{
74 | expect(data.$mixin.message).to.be.equal('hello world ,lll,come on ,It works really well');
75 | expect(this.message).to.be.equal('hello world ,lll,come on ,It works really well');
76 | done()
77 | })
78 | }
79 | }
80 | }).$mount("#vm")
81 | vm.dosome()
82 | });
83 |
84 | });
85 |
86 |
87 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | zcoil
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | > `Zcoil` is a model layer framework for more convenient and elegant data manipulation
13 |
14 | document
15 |
16 | >Currently only Chinese documents are available
17 |
18 | [中文文档](https://channg.github.io/zcoil/)
19 |
20 | Let's start with the demo
21 |
22 | > The demo uses queues to execute methods
23 |
24 | https://channg.github.io/zcoil/demo.html
25 |
26 | use
27 | install zcoil with npm
28 |
29 | ```
30 | npm i zcoil
31 | ```
32 | easy to use in Hello world
33 |
34 | **Instantiated object**
35 |
36 | ```javascript
37 | var z = new zcoil()
38 | ```
39 |
40 | **initialization with param**
41 |
42 | ```javascript
43 | z.init({
44 | data() {
45 | return {
46 | message: "hello world "
47 | }
48 | },
49 | asyncGetSaySomething(param) {
50 | return new Promise((resolve, reject) => {
51 | setTimeout(() => {
52 | resolve(param)
53 | }, 1000)
54 | })
55 | },
56 | say(param) {
57 | this.asyncGetSaySomething(param).then((say) => {
58 | this.message += "," + say
59 | })
60 | },
61 | endToSay(){
62 | this.message += ",come on "
63 | }
64 | })
65 | ```
66 | **Magical method call process with**`$coil()`
67 |
68 | ```javascript
69 | var hl = z.$coil().say("Thank your star this project")
70 |
71 | hl = hl.endToSay()
72 |
73 | hl = hl.say("It works really well")
74 |
75 | hl.exec((data)=>{
76 | data.message //"hello world ,Thank your star this project,come on ,It works really well"
77 | z.message //"hello world ,Thank your star this project,come on ,It works really well"
78 | })
79 | ```
80 |
81 | **You can use the `$watch` method to get the data before the `$coil` method is executed**
82 |
83 | ```javascript
84 | z.$watch((from,to)=>{
85 | console.log(from.message)
86 | console.log(to.message)
87 | })
88 | ```
89 |
90 | test it online
91 |
92 | try it in[ jsfiddle](https://jsfiddle.net/channg/uhfxqsj4/11/)
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/docs/THIRD.md:
--------------------------------------------------------------------------------
1 | # 探索
2 |
3 | 对于`javascript`而言,异步方法的调用,算得上是一个比较令人头痛的问题了。单线程的特性,也从始至终贯彻在我们的code之中。从嵌套的`callback`函数,接着是更优雅的`promise`,再接着变为更趋近于同步写法的`async\await`,或是更优秀的响应式编程库`rxjs`,`javascript`开发者都在进步着。
4 |
5 | `zcoil`也会带来一种全新的异步开发体验。
6 |
7 | ```javascript
8 | var z = new zcoil()
9 | z.init({
10 | data() {
11 | return {
12 | message: "hello world "
13 | }
14 | },
15 | asyncGetName() {
16 | return new Promise((resolve, reject) => {
17 | setTimeout(() => {
18 | resolve('my friend')
19 | }, 2000)
20 | })
21 | },
22 | asyncGetSaySomething(param) {
23 | return new Promise((resolve, reject) => {
24 | setTimeout(() => {
25 | resolve(param)
26 | }, 1000)
27 | })
28 | },
29 | name() {
30 | this.asyncGetName().then((name) => {
31 | this.message += name
32 | })
33 | },
34 | say(param) {
35 | this.asyncGetSaySomething(param).then((say) => {
36 | this.message += "," + say
37 | })
38 | }
39 | })
40 |
41 | z.name()
42 | z.say("how are you ?")
43 | ```
44 |
45 | 这段代码是中最后调用了两个异步方法,我们希望最后的`z.message`的结果是`hello world my friend,how are you ?`。但很明显,因为执行时间的不同,这段代码最后`z.message`的结果是`hello world ,how are you ?my friend`。
46 |
47 | 如何让执行顺序符合我们的预期呢。
48 |
49 | ## $coil
50 |
51 | >$coil 创造方法可以被链式调用的生成器。
52 |
53 | 现在可以对上面的代码进行包装。
54 |
55 | ```javascript
56 | z.$coil().name().say("how are you ?").exec((data)=>{
57 | data.message //hello world my friend,how are you ?
58 | z.message //hello world my friend,how are you ?
59 | })
60 | ```
61 |
62 | 这时候,当链式调用结束的时候调用`exec`,并可以从回调函数中获得执行结束的数据。这时候`z.message`的结果就是`hello world my friend,how are you ?`。
63 |
64 | ### exec
65 | `exec`函数表示执行当前顺序执行之前所有的函数。
66 |
67 | ```javascript
68 | z.$coil().some().exec((data,error)=>{
69 | })
70 | ```
71 | `exec`会在执行钩子的时候传入两个参数。
72 |
73 | `data`与`z.data`内的数据相同,表示执行队列已经完成最终的到的数据。
74 |
75 | `error`表示在之前的函数调用中出现过`reject`,如果没有出现`reject`,`error`将返回`null`。
76 |
77 | 如果再之前的函数调用只返回一个错误,`error`将等于`reject`传递的数据,如果再调用过程中出现了大于一个的错误,`error`会作为一个包含`Error`的数组被返回。
78 | 可以在方法中统一处理`error`
79 |
80 | >tips
81 | >
82 | >不管同步方法,还是异步方法,都可以被链式调用执行,但如果方法含有`return`将会被忽略掉。
83 |
84 | ### 出鞘
85 |
86 | 使用`$coil`确实可以解决一些异步的问题,但是显然是这段代码被运行在同一时间点。如果需要在不同时间执行这些代码,例如`点击事件`之后异步调用,但有部分需要提前获取。
87 |
88 | 所以在`$coil()`之后被链式调用的所以方法,全部会返回一个`$coil`对象,这个对象可以再任何时候被调用。使用`$coil`可以完成全新的异步方法体验。
89 |
90 | ```javascript
91 | var messageGet = z.$coil().name().say("^_^").exec((data)=>{
92 | console.log(data.message) //hello world my friend,^_^
93 | })
94 | messageGet.say("lululu").exec((data)=>{
95 | console.log(data.message) //hello world my friend,^_^,lululu
96 | })
97 | ```
98 |
99 | >tips
100 | >
101 | >`$coil`链式调用执行的方法,只会在`exec`执行的时候被执行。链式调用只是将方法加入到`执行队列中`当执行队列被塞入了`exec`,这个队列将会被顺序调用。
102 |
103 | ### 参数
104 |
105 | `$coil`方法含有几个参数需要注意一下。
106 |
107 | ```javascript
108 | export interface coilConif{
109 | rollback?:Boolean;
110 | errorContinue?:Boolean;
111 | saveWithExec?:Boolean;
112 | }
113 | ```
114 | `rollback`
115 | * 执行链调用中出现异常(`promise.reject`)时是否闪回。默认 `false`
116 |
117 | `errorContinue`
118 | * 执行链调用中出现异常(`promise.reject`)时是否继续执行。默认`true`
119 |
120 | `saveWithExec`
121 | * 执行`exec`时,是否替换闪回数据,此参数需要配合`rollback`使用,默认`true`
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Getting Started
4 |
5 |
6 |
12 |
21 |
53 |
54 |
55 |
56 |
The asynchronous method terminates the solution, using queues
57 |
58 |
59 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/docs/WHY.md:
--------------------------------------------------------------------------------
1 | # 理解
2 | 在学习zcoil之前,现在看一看为什么要使用`zcoil`。
3 |
4 | 来看这段普通的代码
5 | ```javascript
6 | function findFood(){
7 | //asyncToFindFood
8 | ...
9 | }
10 |
11 | function eat(food){
12 | ...
13 | }
14 | ```
15 |
16 | 有一个function `findFood`,还有一个function `eat`。在程序执行的某个时间点,我会调用`findeFood`,这时候我派出了一个机器人`async`异步去寻找食物,毕竟寻找食物是要耗时的。
17 |
18 | 如果想要让`findFood`找到食物之后,吃掉这个食物。那`eat`方法就必须要在`asyncToFindFood`之后被调用。有如下代码
19 | ```javascript
20 | function findFood(){
21 | asyncToFindFood(function(food){
22 | eat(food)
23 | })
24 | }
25 | ```
26 | 很显然,这种嵌套代码不完美,有什么问题呢。
27 | * 美观性差
28 | * 后期维护复杂
29 | * 对异常处理很困难
30 |
31 | 所以说我们现在,需要一个更优秀的写法,来规避这些问题。
32 | 很开心的是,我们拥有了`async/await`
33 |
34 | 代码就就如下:
35 | ```javascript
36 | async function findFoodAndEat(){
37 | var food = await asyncToFindFood()
38 | eat(food)
39 | }
40 | ```
41 | 使用了`async/awiait`之后,程序美观了许多,如果发生异常,也可以直接使用`try catch`去捕获。
42 |
43 | 继续阅读这段代码,会发现一个问题,通过`asyncToFindFood`找到了多少食物,就必须要`eat`多少。
44 |
45 | 这时候的需求来了,在`findFood`的时候,我们找到的不只是只够一次吃的食物,找到的食物是无穷的,也就是说只要`findFood`成功一次,以后就不需要再进行`findFood`了,那么我们就需要在寻找的到食物的时候要存储起来,下次也可以去`eat`
46 | 这个时候,我们就需要调整代码内部的逻辑。
47 |
48 | 所以代码如下:
49 | ```javascript
50 | var food
51 | async function findFood(){
52 | if(!food)
53 | food = await asyncToFindFood()
54 | eat(food)
55 | }
56 | ```
57 | 上面的代码,表示,找到了食物要存储起来,如果下次再调用方法,我就去查看一下是不是有食物,如果有食物,我就不再`findFood`了,直接`eat`
58 |
59 | 这时候,新的需求又来了,我现在有了一个闹铃,闹铃响了的时候代表我饿了,必须要`eat`,程序这时候增加了一个闹铃方法`alarmGoOff`,当闹铃响起的时候`alarmGoOff`会被调用,之后我们就需要调用`eat()`,但是呢我们要保证,在闹钟响了的时候`eat`是能吃到食物的。
60 |
61 | ```javascript
62 | function alarmGoOff(){
63 | eat(food)
64 | }
65 | ```
66 |
67 | 那么我们要怎么保证在`alarmGoOff()`闹铃响了的时候一定能吃到食物呢?
68 |
69 | 想了一下,决定在页面加载的时候调用`findFood`。只要程序一开始运行我就先去找食物,这样之后我都会有食物,是不是可行呢?
70 |
71 | ```javascript
72 | function init(){
73 | findFood()
74 | }
75 | init()
76 | ```
77 |
78 | 但总有事情不凑巧,虽然在程序一开始执行就调用了`findFood`,但因为`findFood`是异步的,闹铃正好在你`findFood`期间响起来了,由于`javascript`单线程的原因,又因为`EventLoop`模型。
79 |
80 | 这时候你无法等待`findFood`结束了,直接触发了`alarmGoOff`里面的方法`eat`。
81 | 但是很明显这个时候`food`是`null`
82 | 你吃掉了一口`null`
83 | 就这样,嘎嘣一声程序就挂了。
84 |
85 | 在实际的场景中,我们经常性的会遇到这种问题,比如说一个点击事件依赖一个异步数据,这个异步数据在程序初始化的时候被执行,但有时候因为网速的原因啊,用户进行点击事件的时候异步数据还并没有返回,这时候就造成了异常。
86 |
87 | 通常我们用最简单的解决办法。**在闹铃响起来的时候,也先去寻找食物**,然后当程序触发`findFood`的时候,也去寻找食物,两者谁先进行,谁就先保存食物。
88 |
89 | ```javascript
90 | var food
91 | async function alarmGoOff(){
92 | if(!food)
93 | food = await asyncToFindFood()
94 | eat(food)
95 | }
96 |
97 | async function findFood(){
98 | if(!food)
99 | food = await asyncToFindFood()
100 | eat(food)
101 | }
102 | ```
103 | 😭但是,总感觉,这两个代码好像一毛一样。一个是普通的程序执行过程中的`findFood`,另外一个是`alarmGoOff`因为闹铃响了要去吃东西。两者的代码有很大的冗余。但是这样,确实是能够保证程序没有异常
104 |
105 | 但就算如此,现在代码没有问题吗?
106 | 虽然在两个函数中都判断了`food`是否存在,但如果两者被调用的时候,两个函数都没有被返回,那么就会触发两次`asyncToFindFood()`,因为`async/awaut`本质还是异步的。虽然这样不会对程序造成异常。但貌似还是不完美。那么我们应该怎么样解决呢?
107 |
108 | 当某一个函数,在调用`asyncToFindFood`的时候,设置一个变量表示正在请求,你就不用请求了等着就行了。
109 |
110 | 看下面的代码
111 |
112 | ```javascript
113 | var food
114 | var wait
115 | async function alarmGoOff(){
116 | if(!food&&!wait){
117 | wait = new Promise(()=>{
118 | food = await asyncToFindFood()
119 | resolve()
120 | })
121 | }else if(wait&&!food){
122 | awiat wait
123 | }
124 |
125 | eat(food)
126 | }
127 | ```
128 |
129 | 这段代码表示
130 | * 如果没有`food`也没有`wait`,那么我们就生成一个`Promise`表示:后面的你等着吧,前面的机器人正在找食物呢,如果你也要找食物,就等我找完了再说。
131 | * 如果没有`food`但是有`wait`,很明显就是前面的机器人已经去找食物了,但是还没有回来,我们等着找完了回来直接`eat`就行了,不用再去找一遍。
132 | * 最后一种就是已经有`food`了 直接开吃
133 |
134 | 终于完美了,但是看这段代码像什么?
135 | 一个标志表示事件是否结束,如果没有结束,就等待,如果结束了,就立刻执行。
136 | 是不是,像是一个消息队列。哈哈哈,其实是因为`zcoil`就是实现了一个这样的消息队列。
137 |
138 | 使用`zcoil`超级简单的处理这种问题。
139 |
140 | 使用`zcoil`生成一个消息队列
141 |
142 | ```javascript
143 | z.$coil()
144 | ```
145 |
146 | 在初始化的时候在方法消息队列里插入一个`findFood`方法
147 |
148 | ```javascript
149 | z.$coil().findFood()
150 | ```
151 |
152 | 不用担心,这个时候,`findFood`不会被执行,队列只有在调用`exec`方法的时候被执行。
153 |
154 | ok,这时候闹钟响了怎么办,很简单。只需要将队列保存下来,在闹钟响了的时候,在队列里插入`eat()`,并调用`exec()`执行队列就可以了。当然,返回值还是一个队列,可以继续被调用。
155 |
156 | ```javascript
157 | var some = z.$coil().findFood()
158 |
159 | function alarmGoOff(){
160 | var some = some.eat().exec()
161 | }
162 |
163 | ```
164 |
165 | 使用`zcoil`生成队列添加的函数,永远都在前一个方法结束的时候被执行,后面的方法总会等待前面的方法结束,而且使用起来非常方便,可以说是前端异步请求的终极解决方案。是不是很酷?
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/src/coil.ts:
--------------------------------------------------------------------------------
1 | import forIn =require('lodash/forIn');
2 | import assign = require('lodash/assign');
3 | import {coilConif} from './interface/CoilConfig'
4 |
5 | export class coil {
6 | pArray: any[] = [];
7 | [key: string]: any;
8 | _call_index: any = 0;
9 | _callback: Function;
10 | _model: any;
11 | _call_stack: any[] = [];
12 | _zcoil: any;
13 | _error: any
14 | _default_config: coilConif = {
15 | rollback: false,
16 | errorContinue: true,
17 | saveWithExec: true
18 | }
19 | _ncoil: any
20 | _rollback_data_: any = {}
21 | _wait: any = null
22 | _next_exec: Function
23 |
24 | constructor(zcoil: any, config?: coilConif, wait?: any) {
25 | if (wait) {
26 | this._wait = wait
27 | }
28 | assign(this._default_config, config)
29 | // 注意 rollback 的数据 将为 $coil 被调用时的数据,如果调用过程中有并行的数据改变,rollback不会记录。
30 | if (this._default_config.rollback) {
31 | this._save_data(zcoil._data)
32 | }
33 |
34 | let that = this
35 | this._zcoil = zcoil
36 | this._model = zcoil._model
37 | this._model.$mixin = zcoil.$mixin
38 | /**
39 | * 初始化调用栈
40 | */
41 | forIn(zcoil._func, (value, key) => {
42 | this[key] = function (...args: any[]) {
43 | that.pArray.push(() => {
44 | zcoil[key].call({
45 | _call: (key: any, type: any,error?:any) => {
46 | that._call_stack.push({[type]: key})
47 | that._ca(key, type,error)
48 | }
49 | }, ...args)
50 | })
51 | return that
52 | }
53 | })
54 | this._add_deserialize(zcoil)
55 | };
56 |
57 | exec(_callback?: Function) {
58 | let nCoil = new coil(this._zcoil, this._default_config, true)
59 | this._ncoil = nCoil
60 | this._callback = _callback
61 | // is the queue is be perform ,do not run _next
62 | if (!this._wait) {
63 | this._next()
64 | }
65 | return nCoil
66 | };
67 |
68 | _add_deserialize(zcoil: any) {
69 | this.$deserialize = (...args: any[]) => {
70 | this._call_stack.push({push: 'deserialize'})
71 | this._ca('deserialize', 'push')
72 | zcoil.$deserialize(...args).then((data: any) => {
73 | this._call_stack.push({pop: 'deserialize'})
74 | this._ca('deserialize', 'pop')
75 | })
76 | return this
77 | }
78 | }
79 |
80 | _next() {
81 | if (this.pArray.length > 0) {
82 | this.pArray.shift()()
83 | } else {
84 | this._check_call_array()
85 | }
86 | };
87 |
88 | _ca(key: any, type: String,error?:any) {
89 | if (type === 'push') {
90 | ++this._call_index
91 | } else if (type === 'pop' || (this._default_config.errorContinue && type === 'err')) {
92 | --this._call_index
93 | if (type === 'err') {
94 | this._set_error(error)
95 | }
96 | this._check_call_array()
97 | } else if (type === 'err' && !this._default_config.errorContinue) {
98 | this._call_index = 0
99 | this.pArray = []
100 | this._error = new Error('The call chain has reject')
101 | this._check_call_array()
102 | }
103 | };
104 |
105 | /**
106 | * When only one error occurs in the queue, the error is returned, and when two or more errors occur, an array is returned
107 | * @param error
108 | * @private
109 | */
110 | _set_error(error: any) {
111 | if(!error){
112 | error = new Error('no message reject')
113 | }
114 | if (!this._error) {
115 | this._error = error
116 | } else {
117 | if (Array.isArray(this._error)) {
118 | this._error.push(error)
119 | } else {
120 | this._error = [this._error, error]
121 | }
122 | }
123 | }
124 |
125 | _check_call_array() {
126 | if (this._call_index === 0&&this.pArray.length > 0) {
127 | this._next()
128 | }
129 | //done the queue
130 | else if (this._call_index === 0 && this.pArray.length === 0) {
131 | if (this._callback) {
132 | this._zcoil._dataTransToThis()
133 | //Check whether the data is rolled back
134 | if (!!this._error && this._default_config.rollback) {
135 | this._zcoil._dataTransToThis(this._rollback_data_)
136 | }
137 | this._callback.call(this._zcoil, this._model, this._error)
138 | this._error = null
139 | this._call_stack = []
140 | }
141 | //next exec : if this._ncoil.pArray.length >0 means the next queue is be perform
142 | if (this._ncoil.pArray.length > 0) {
143 | //check saveWithExec
144 | if (this._ncoil._default_config.rollback && this._ncoil._default_config.saveWithExec) {
145 | this._ncoil._save_data(this._zcoil._data)
146 | }
147 | this._ncoil._next()
148 | } else {
149 | this._ncoil._wait = false
150 | }
151 | }
152 | };
153 |
154 | _save_data(data: any) {
155 | forIn(data, (value, key) => {
156 | this._rollback_data_[key] = value
157 | })
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/test/zcoil-test.js:
--------------------------------------------------------------------------------
1 | var zcoil = require('../dist/zcoil')
2 | const assert = require('assert');
3 | var z = new zcoil()
4 | var z0 = new zcoil()
5 | z0.init({
6 | data:{
7 | a:1
8 | }
9 | })
10 | z.init({
11 | data() {
12 | return {
13 | index: 0
14 | }
15 | },
16 | fetch2() {
17 | return Promise.resolve(2)
18 | },
19 | timeout() {
20 | return new Promise((resolve) => {
21 | setTimeout(() => {
22 | resolve(20)
23 | }, 500)
24 | })
25 | },
26 | addIndex() {
27 | this.fetch2().then((data) => {
28 | this.index += data
29 | })
30 | },
31 | multiply() {
32 | this.timeout().then((data) => {
33 | this.index *= data
34 | })
35 | },
36 | assignment() {
37 | this.index = 200
38 | }
39 | })
40 |
41 | var z2 = new zcoil()
42 | z2.init({
43 | data() {
44 | return {
45 | index: 0
46 | }
47 | },
48 | assignment() {
49 | this.index = 200
50 | }
51 | }
52 | )
53 |
54 | var z3 = new zcoil()
55 | z3.init({
56 | data() {
57 | return {
58 | index: 2,
59 | type:'last'
60 | }
61 | },
62 | assignment() {
63 | this.index = 200
64 | }
65 | }
66 | )
67 |
68 | var z4 = new zcoil()
69 | z4.init({
70 | data() {
71 | return {
72 | index: 4
73 | }
74 | },
75 | assignment() {
76 | this.index = 300
77 | }
78 | }
79 | )
80 |
81 | var zassign = zcoil.$assign(z3,z4)
82 |
83 | var z5 = new zcoil()
84 | z5.init({
85 | data() {
86 | return {
87 | index: 4
88 | }
89 | },
90 | settimeout() {
91 | var that = this
92 | setTimeout(function(){
93 | z5.index = 100
94 | that.$commit()
95 | },200)
96 | }
97 | }
98 | )
99 | z5.$watch(function(from,to){
100 | })
101 | z5.settimeout()
102 |
103 | var z6 = new zcoil()
104 | z6.init({
105 | data() {
106 | return {
107 | index: 4
108 | }
109 | },
110 | assignment() {
111 | this.index = 300
112 | }
113 | }
114 | )
115 |
116 | var z7 = new zcoil({});
117 | z7.init({
118 | data() {
119 | return {
120 | index: 4
121 | }
122 | },
123 | luck(){
124 | return new Promise((resolve)=>{
125 | setTimeout(()=>{
126 | resolve(8)
127 | },800)
128 | })
129 | },
130 | some(){
131 | this.luck().then((da)=>{
132 | this.index+=da
133 | })
134 | },
135 | jj(){
136 | this.luck().then((da)=>{
137 | this.index*=da
138 | })
139 | }
140 | }
141 | );
142 |
143 | var z8 = new zcoil({});
144 | z8.init({
145 | data() {
146 | return {
147 | index: 4
148 | }
149 | },
150 | reject(){
151 | return Promise.reject()
152 | },
153 | resolve(){
154 | return Promise.resolve(2)
155 | },
156 | aa(){
157 | this.resolve().then((data)=>{
158 | this.index+=data
159 | })
160 | },
161 | bb(){
162 | this.reject().then((data)=>{
163 | this.index+=data
164 | }).catch(()=>{
165 | //donothing
166 | })
167 | }
168 | }
169 | );
170 |
171 | var z9 = new zcoil({});
172 | z9.init({
173 | data() {
174 | return {
175 | index: 4
176 | }
177 | },
178 | reject(){
179 | return Promise.reject()
180 | },
181 | resolve(){
182 | return Promise.resolve(2)
183 | },
184 | aa(){
185 | this.resolve().then((data)=>{
186 | this.index+=data
187 | })
188 | },
189 | bb(){
190 | this.reject().then((data)=>{
191 | this.index+=data
192 | }).catch(()=>{
193 | //donothing
194 | })
195 | }
196 | }
197 | );
198 |
199 | var z10 = new zcoil()
200 | z10.init({
201 | data() {
202 | return {
203 | message: "hello world "
204 | }
205 | },
206 | asyncGetName() {
207 | return new Promise((resolve, reject) => {
208 | setTimeout(() => {
209 | resolve('my friend')
210 | }, 100)
211 | })
212 | },
213 | asyncGetSaySomething(param) {
214 | return new Promise((resolve, reject) => {
215 | setTimeout(() => {
216 | reject(param)
217 | }, 200)
218 | })
219 | },
220 | name() {
221 | this.asyncGetName().then((name) => {
222 | this.message += name
223 | })
224 | },
225 | say(param) {
226 | this.asyncGetSaySomething(param).then((say) => {
227 | this.message += "," + say
228 | }).catch(()=>{})
229 | }
230 | })
231 |
232 |
233 | describe('|||| ZCOIL MOCHA TEST ||||', () => {
234 | it('use data as a Object', () => {
235 | assert.strictEqual(z0.a , 1);
236 | });
237 | it('use zcoil', () => {
238 | assert.strictEqual(zcoil !== null, true);
239 | });
240 | it('new zcoil();', () => {
241 | assert.strictEqual(z !== null, true);
242 | });
243 | it('init z.index', () => {
244 | assert.strictEqual(z.index, 0);
245 | });
246 |
247 | it('z.fetch()', (done) => {
248 | z.fetch2().then((data) => {
249 | assert.strictEqual(data, 2);
250 | done()
251 | })
252 | });
253 | it('z.$watch()', (done) => {
254 | z2.$watch((from, to) => {
255 | assert.strictEqual(z2.index, to.index);
256 | done()
257 | })
258 | z2.assignment()
259 | });
260 |
261 |
262 | it('z.$coil().addIndex().multiply().assignment().multiply()', (done) => {
263 | z.$coil().addIndex().multiply().assignment().multiply().exec(function(data){
264 | assert.strictEqual(z.index, 4000);
265 | assert.strictEqual(data.index, 4000);
266 | assert.strictEqual(this.index, 4000);
267 | done()
268 | })
269 | });
270 |
271 | it('zcoil.$assign()', () => {
272 | assert.strictEqual(zassign.index, 4);
273 | assert.strictEqual(zassign.type, 'last');
274 | });
275 |
276 | it('zcoil.$assign().method()', () => {
277 | zassign.assignment()
278 | assert.strictEqual(zassign.index, 300);
279 | });
280 |
281 | it('z.$watch() by $commit', (done) => {
282 | z6.$watch((from, to) => {
283 | assert.strictEqual(z6.index, 200);
284 | assert.strictEqual(from.index, 4);
285 | assert.strictEqual(to.index, 200);
286 | done()
287 | })
288 | z6.index = 200
289 | z6.$commit()
290 | });
291 | var some = null
292 | it('zcoil.$coil two exec', (done) => {
293 | some = z7.$coil().some().exec(function () {
294 |
295 | }).jj().exec(function (data) {
296 | assert.strictEqual(data.index, 96);
297 | assert.strictEqual(z7.index, 96);
298 | done()
299 | })
300 | });
301 | it('zcoil.$coil next exec', (done) => {
302 | some.some().exec(function(data){
303 | assert.strictEqual(z7.index, 104);
304 | assert.strictEqual(data.index, 104);
305 | done()
306 | })
307 | });
308 |
309 |
310 | it('zcoil more one exec() use saveWithExec = false and rollback = true.', (done) => {
311 | z8.$coil({rollback:true,saveWithExec:false}).aa().exec(function(data){
312 |
313 | }).bb().exec(function (data,error) {
314 | assert.strictEqual(z8.index, 4);
315 | assert.strictEqual(data.index, 4);
316 | done()
317 | })
318 | });
319 | it('zcoil more one exec() use rollback = true but saveWithExec = true.', (done) => {
320 | z9.$coil({rollback:true,saveWithExec:true}).aa().exec(function(data){
321 | debugger
322 | }).bb().exec(function (data,error) {
323 | assert.strictEqual(z9.index, 6);
324 | assert.strictEqual(data.index, 6);
325 | done()
326 | })
327 | });
328 | it('z.$coir() exec one error ', (done) => {
329 | z10.$coil().say('err').name().exec(function (data,error) {
330 | assert.strictEqual(error,'err');
331 | done()
332 | })
333 | });
334 |
335 | })
336 |
337 |
338 |
339 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import assign = require('lodash/assign');
2 | import cloneDeep = require('lodash/cloneDeep');
3 | import forIn = require('lodash/forIn');
4 | import merge =require('lodash/merge');
5 | import {getTimestamp, isPromise,isFunction} from './utils'
6 | import {coil} from './coil'
7 | import {coilConif} from './interface/coilConfig'
8 | import {zcoilConif} from './interface/zcoilConig'
9 | import {watch} from './watch'
10 | import scoil from './scoil'
11 | import {getData, serializeData} from "./serialize";
12 | import {install} from './vue';
13 | class zcoil {
14 | constructor(config?: zcoilConif) {
15 | this.install = install
16 | if (config) {
17 | config = assign({}, zcoil._init_config, config)
18 | this._config = config
19 | this.$mixin = config.mixin
20 | }
21 | }
22 | [key: string]: any;
23 | private _config: any = {}
24 | private _data: any = null;
25 | private _func: any = {};
26 | _watch_array: any[] = []
27 | $mixin:any = {}
28 |
29 | static _init_config = {
30 | localStorage: true,
31 | deadline: 30 * 24 * 3600 ,
32 | cover: true,
33 | mixin:{}
34 | }
35 |
36 | static $assign(...datas: any[]) {
37 | let _merge = merge({}, ...datas)
38 | let _merge_func = cloneDeep(_merge._func)
39 | let _config: any = {
40 | data() {
41 | return cloneDeep(_merge._data)
42 | }
43 | }
44 | forIn(_merge_func, (value: any, key: any) => {
45 | _config[key] = value
46 | })
47 | let _assign_obj = new zcoil()
48 | _assign_obj.init(_config)
49 | return _assign_obj
50 | }
51 |
52 | $coil(args?: coilConif) {
53 | return new coil(this, args)
54 | };
55 |
56 | $watch(callback?: Function): void;
57 | $watch(expression?: String | Array, callback?: Function): void;
58 | $watch(expression?: any, callback?: Function) {
59 | if (typeof expression === 'function') {
60 | this._watch_array.push(new watch(null, expression, cloneDeep(this._data)))
61 | }
62 | else {
63 | this._watch_array.push(new watch(expression, callback, cloneDeep(this._data)))
64 | }
65 | }
66 |
67 | $commit() {
68 | if (this.$zcoil) {
69 | this.$zcoil._dataTransToThis.call(this.$zcoil, this)
70 | } else {
71 | this._dataTransToThis.call(this, this)
72 | }
73 | }
74 |
75 | _push_dictate(model: any) {
76 | model.$commit = this.$commit
77 | }
78 |
79 | /**
80 | * init 方法初始化数据,并绑定方法,根据返回值不同,在不同时刻进行不同操作监听数据变动,
81 | * @param data
82 | * @param func
83 | */
84 | init({data, ...func}: any) {
85 | this._model = {}
86 | this._serialize()
87 | if(data){
88 | if(isFunction(data)){
89 | this._data = data()
90 | }else{
91 | this._data = cloneDeep(data)
92 | }
93 | }else{
94 | this._data = {}
95 | }
96 | func.$deserialize = this.$deserialize
97 | this._func = func
98 | let that = this
99 | forIn(func, (value, key) => {
100 | this[key] = this._model[key] = function (...arg: any[]) {
101 | let _to_model: any = that._model
102 | if (this._call) {
103 | _to_model = new scoil(that._model, this, that._data).model
104 | }
105 | _to_model.$zcoil = that
106 | that._push_dictate(_to_model)
107 | if (this._call) {
108 | this._call(key, 'push')
109 | }
110 | that._before(key)
111 | that._dataTransToThis(_to_model)
112 | _to_model.$mixin = that._config.mixin
113 | let _mr = value.apply(_to_model, arg)
114 | if (_mr) {
115 | if (isPromise(_mr)) {
116 | return new Promise((reserve, reject) => {
117 | const _calls = this._call
118 | _mr.then((datas: any) => {
119 | reserve(datas)
120 | Promise.resolve().then(() => {
121 | that._after(key, _to_model)
122 | that._dataTransToThis(this)
123 | if (_calls) {
124 | _calls(key, 'pop')
125 | }
126 | })
127 | }).catch((error: any) => {
128 | reject(error)
129 | Promise.resolve().then(() => {
130 | that._error(key, _to_model)
131 | if (_calls) {
132 | _calls(key, 'err',error)
133 | }
134 | })
135 | })
136 | })
137 | } else {
138 | that._dataTransToThis(_to_model)
139 | if (this._call) {
140 | this._call(key, 'pop')
141 | }
142 | that._after(key, _to_model)
143 | return _mr
144 | }
145 | } else {
146 | that._dataTransToThis(_to_model)
147 | if (this._call) {
148 | this._call(key, 'pop')
149 | }
150 | that._after(key, _to_model)
151 | }
152 | }
153 | })
154 | this._dataTransToThis()
155 |
156 | };
157 |
158 | /**
159 | * 反序列化数据方法
160 | */
161 | $deserialize() {
162 | let that = this.$zcoil || this
163 | return new Promise((resolve) => {
164 | if (that._config && that._config.name && that._config.localStorage) {
165 | getData(that._config.name).then((d) => {
166 | if (d && that._config.cover) {
167 | that._data = d
168 | that._dataTransToThis(d)
169 | resolve(that._data)
170 | } else if (d) {
171 | resolve(d)
172 | } else {
173 | resolve(that._data)
174 | }
175 | })
176 | } else {
177 | resolve(that._data)
178 | }
179 | })
180 |
181 | }
182 |
183 | private _before(key: String) {
184 | //console.log('before:' + key)
185 | };
186 |
187 | private _after(key: any, _to_model: any) {
188 | this._dataTransToThis(_to_model)
189 | //console.log('after:' + key)
190 | };
191 |
192 | private _error(key: String, _to_model: any) {
193 | this._dataTransToThis(_to_model)
194 | //console.log('error:' + key)
195 | };
196 |
197 | private _watch_each_call(to: any) {
198 | if (this._watch_array.length > 0) {
199 | this._watch_array.forEach((_watch) => {
200 | _watch._on_data_change(to)
201 | })
202 | }
203 | }
204 |
205 | private _serialize() {
206 | if (this._config && this._config.name && this._config.localStorage) {
207 | this.$watch((from: any, to: any) => {
208 | if (from) {
209 | serializeData(this._config.name, this._data).catch(() => {
210 | throw new Error('new zcoil(); serialize error');
211 | })
212 | serializeData(`_${this._config.name}_deadline`, getTimestamp() + this._config.deadline * 1000).catch(() => {
213 | throw new Error('new zcoil(); serialize error');
214 | })
215 | }
216 | })
217 | }
218 | }
219 |
220 | private _dataTransToThis(_to_model?: any) {
221 | forIn(this._data, (value, key) => {
222 | if (!!_to_model) {
223 | this._data[key] = this[key] = value = this._model[key] = _to_model[key]
224 | }
225 | else if (!!this._model[key]) {
226 | this._data[key] = this[key] = value = this._model[key]
227 | }
228 | else {
229 | this._data[key] = this[key] = this._model[key] = value
230 | }
231 | })
232 | if (this._watch_array.length > 0) {
233 | this._watch_each_call(this._data)
234 | }
235 | };
236 | }
237 |
238 | export default zcoil
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/dist/zcoil.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.zcoil=e():t.zcoil=e()}(this,function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=168)}([function(t,e,n){var r=n(61),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();t.exports=i},function(t,e){var n=Array.isArray;t.exports=n},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(167),o=n(162);t.exports=function(t,e){var n=o(t,e);return r(n)?n:void 0}},function(t,e,n){var r=n(37),o=n(36);t.exports=function(t,e,n,i){var a=!n;n||(n={});for(var c=-1,u=e.length;++c-1&&t%1==0&&t-1&&t%1==0&&t<=9007199254740991}},function(t,e){t.exports=function(t){return t}},function(t,e,n){var r=n(6),o=n(3);t.exports=function(t){if(!o(t))return!1;var e=r(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}},function(t,e,n){var r=n(62);t.exports=function(t,e,n){"__proto__"==e&&r?r(t,e,{configurable:!0,enumerable:!0,value:n,writable:!0}):t[e]=n}},function(t,e,n){var r=n(36),o=n(9),i=Object.prototype.hasOwnProperty;t.exports=function(t,e,n){var a=t[e];i.call(t,e)&&o(a,n)&&(void 0!==n||e in t)||r(t,e,n)}},function(t,e,n){var r=n(20);t.exports=function(t){if("string"==typeof t||r(t))return t;var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}},function(t,e,n){var r=n(1),o=n(77),i=n(76),a=n(73);t.exports=function(t,e){return r(t)?t:o(t,e)?[t]:i(a(t))}},function(t,e,n){var r=n(88),o=n(85),i=n(84);t.exports=function(t,e,n,a,c,u){var f=1&n,s=t.length,l=e.length;if(s!=l&&!(f&&l>s))return!1;var v=u.get(t);if(v&&u.get(e))return v==e;var h=-1,p=!0,d=2&n?new r:void 0;for(u.set(t,e),u.set(e,t);++h1?n[i-1]:void 0,c=i>2?n[2]:void 0;for(a=t.length>3&&"function"==typeof a?(i--,a):void 0,c&&o(n[0],n[1],c)&&(a=i<3?void 0:a,i=1),e=Object(e);++r=43)}}).catch(function(){return!1})}(t).then(function(t){return v=t})}function b(t){var e=h[t.name],n={};n.promise=new a(function(t,e){n.resolve=t,n.reject=e}),e.deferredOperations.push(n),e.dbReady?e.dbReady=e.dbReady.then(function(){return n.promise}):e.dbReady=n.promise}function g(t){var e=h[t.name].deferredOperations.pop();if(e)return e.resolve(),e.promise}function m(t,e){var n=h[t.name].deferredOperations.pop();if(n)return n.reject(e),n.promise}function x(t,e){return new a(function(n,r){if(h[t.name]=h[t.name]||{forages:[],db:null,dbReady:null,deferredOperations:[]},t.db){if(!e)return n(t.db);b(t),t.db.close()}var i=[t.name];e&&i.push(t.version);var a=o.open.apply(o,i);e&&(a.onupgradeneeded=function(e){var n=a.result;try{n.createObjectStore(t.storeName),e.oldVersion<=1&&n.createObjectStore(l)}catch(n){if("ConstraintError"!==n.name)throw n;console.warn('The database "'+t.name+'" has been upgraded from version '+e.oldVersion+" to version "+e.newVersion+', but the storage "'+t.storeName+'" already exists.')}}),a.onerror=function(t){t.preventDefault(),r(a.error)},a.onsuccess=function(){n(a.result),g(t)}})}function j(t){return x(t,!1)}function w(t){return x(t,!0)}function O(t,e){if(!t.db)return!0;var n=!t.db.objectStoreNames.contains(t.storeName),r=t.versiont.db.version;if(r&&(t.version!==e&&console.warn('The database "'+t.name+"\" can't be downgraded from version "+t.db.version+" to version "+t.version+"."),t.version=t.db.version),o||n){if(n){var i=t.db.version+1;i>t.version&&(t.version=i)}return!0}return!1}function S(t){return i([function(t){for(var e=t.length,n=new ArrayBuffer(e),r=new Uint8Array(n),o=0;o0&&(!t.db||"InvalidStateError"===o.name||"NotFoundError"===o.name))return a.resolve().then(function(){if(!t.db||"NotFoundError"===o.name&&!t.db.objectStoreNames.contains(t.storeName)&&t.version<=t.db.version)return t.db&&(t.version=t.db.version+1),w(t)}).then(function(){return function(t){b(t);for(var e=h[t.name],n=e.forages,r=0;r>4,s[u++]=(15&r)<<4|o>>2,s[u++]=(3&o)<<6|63&i;return f}function Q(t){var e,n=new Uint8Array(t),r="";for(e=0;e>2],r+=T[(3&n[e])<<4|n[e+1]>>4],r+=T[(15&n[e+1])<<2|n[e+2]>>6],r+=T[63&n[e+2]];return n.length%3==2?r=r.substring(0,r.length-1)+"=":n.length%3==1&&(r=r.substring(0,r.length-2)+"=="),r}var K={serialize:function(t,e){var n="";if(t&&(n=G.call(t)),t&&("[object ArrayBuffer]"===n||t.buffer&&"[object ArrayBuffer]"===G.call(t.buffer))){var r,o=N;t instanceof ArrayBuffer?(r=t,o+=D):(r=t.buffer,"[object Int8Array]"===n?o+=B:"[object Uint8Array]"===n?o+=C:"[object Uint8ClampedArray]"===n?o+=F:"[object Int16Array]"===n?o+=M:"[object Uint16Array]"===n?o+=$:"[object Int32Array]"===n?o+=L:"[object Uint32Array]"===n?o+=U:"[object Float32Array]"===n?o+=W:"[object Float64Array]"===n?o+=q:e(new Error("Failed to get type for BinaryArray"))),e(o+Q(r))}else if("[object Blob]"===n){var i=new FileReader;i.onload=function(){var n="~~local_forage_type~"+t.type+"~"+Q(this.result);e(N+R+n)},i.readAsArrayBuffer(t)}else try{e(JSON.stringify(t))}catch(n){console.error("Couldn't convert value into a JSON string: ",t),e(null,n)}},deserialize:function(t){if(t.substring(0,P)!==N)return JSON.parse(t);var e,n=t.substring(V),r=t.substring(P,V);if(r===R&&z.test(n)){var o=n.match(z);e=o[1],n=n.substring(o[0].length)}var a=H(n);switch(r){case D:return a;case R:return i([a],{type:e});case B:return new Int8Array(a);case C:return new Uint8Array(a);case F:return new Uint8ClampedArray(a);case M:return new Int16Array(a);case $:return new Uint16Array(a);case L:return new Int32Array(a);case U:return new Uint32Array(a);case W:return new Float32Array(a);case q:return new Float64Array(a);default:throw new Error("Unkown type: "+r)}},stringToBuffer:H,bufferToString:Q};function X(t,e,n,r){t.executeSql("CREATE TABLE IF NOT EXISTS "+e.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],n,r)}function J(t,e,n,r,o,i){t.executeSql(n,r,o,function(t,a){a.code===a.SYNTAX_ERR?t.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?",[e.storeName],function(t,c){c.rows.length?i(t,a):X(t,e,function(){t.executeSql(n,r,o,i)},i)},i):i(t,a)},i)}var Y={_driver:"webSQLStorage",_initStorage:function(t){var e=this,n={db:null};if(t)for(var r in t)n[r]="string"!=typeof t[r]?t[r].toString():t[r];var o=new a(function(t,r){try{n.db=openDatabase(n.name,String(n.version),n.description,n.size)}catch(t){return r(t)}n.db.transaction(function(o){X(o,n,function(){e._dbInfo=n,t()},function(t,e){r(e)})},r)});return n.serializer=K,o},_support:"function"==typeof openDatabase,iterate:function(t,e){var n=this,r=new a(function(e,r){n.ready().then(function(){var o=n._dbInfo;o.db.transaction(function(n){J(n,o,"SELECT * FROM "+o.storeName,[],function(n,r){for(var i=r.rows,a=i.length,c=0;c0)return void a(t.apply(i,[e,u,r,o-1]));c(n)}})})}).catch(c)});return c(u,r),u}.apply(this,[t,e,n,1])},removeItem:function(t,e){var n=this;t=f(t);var r=new a(function(e,r){n.ready().then(function(){var o=n._dbInfo;o.db.transaction(function(n){J(n,o,"DELETE FROM "+o.storeName+" WHERE key = ?",[t],function(){e()},function(t,e){r(e)})})}).catch(r)});return c(r,e),r},clear:function(t){var e=this,n=new a(function(t,n){e.ready().then(function(){var r=e._dbInfo;r.db.transaction(function(e){J(e,r,"DELETE FROM "+r.storeName,[],function(){t()},function(t,e){n(e)})})}).catch(n)});return c(n,t),n},length:function(t){var e=this,n=new a(function(t,n){e.ready().then(function(){var r=e._dbInfo;r.db.transaction(function(e){J(e,r,"SELECT COUNT(key) as c FROM "+r.storeName,[],function(e,n){var r=n.rows.item(0).c;t(r)},function(t,e){n(e)})})}).catch(n)});return c(n,t),n},key:function(t,e){var n=this,r=new a(function(e,r){n.ready().then(function(){var o=n._dbInfo;o.db.transaction(function(n){J(n,o,"SELECT key FROM "+o.storeName+" WHERE id = ? LIMIT 1",[t+1],function(t,n){var r=n.rows.length?n.rows.item(0).key:null;e(r)},function(t,e){r(e)})})}).catch(r)});return c(r,e),r},keys:function(t){var e=this,n=new a(function(t,n){e.ready().then(function(){var r=e._dbInfo;r.db.transaction(function(e){J(e,r,"SELECT key FROM "+r.storeName,[],function(e,n){for(var r=[],o=0;o '__WebKitDatabaseInfoTable__'",[],function(n,r){for(var o=[],i=0;i0?(this._dbInfo=e,e.serializer=K,a.resolve()):a.reject()},_support:function(){try{return"undefined"!=typeof localStorage&&"setItem"in localStorage&&!!localStorage.setItem}catch(t){return!1}}(),iterate:function(t,e){var n=this,r=n.ready().then(function(){for(var e=n._dbInfo,r=e.keyPrefix,o=r.length,i=localStorage.length,a=1,c=0;c=0;n--){var r=localStorage.key(n);0===r.indexOf(t)&&localStorage.removeItem(r)}});return c(n,t),n},length:function(t){var e=this.keys().then(function(t){return t.length});return c(e,t),e},key:function(t,e){var n=this,r=n.ready().then(function(){var e,r=n._dbInfo;try{e=localStorage.key(t)}catch(t){e=null}return e&&(e=e.substring(r.keyPrefix.length)),e});return c(r,e),r},keys:function(t){var e=this,n=e.ready().then(function(){for(var t=e._dbInfo,n=localStorage.length,r=[],o=0;o=0;e--){var n=localStorage.key(e);0===n.indexOf(t)&&localStorage.removeItem(n)}}):a.reject("Invalid arguments"),e),r}},et=function(t,e){for(var n=t.length,r=0;ro.getTimestamp()?r.getItem(t).then(function(t){e(t)}).catch(function(){e()}):(e(),r.removeItem(t),r.removeItem("_"+t+"_deadline"))})})}},function(t,e,n){var r=n(39),o=n(31),i=n(1),a=n(32),c=n(33),u=n(38);t.exports=function(t,e,n){for(var f=-1,s=(e=r(e,t)).length,l=!1;++f0?this.pArray.shift()():this._check_call_array()}},{key:"_ca",value:function(t,e,n){"push"===e?++this._call_index:"pop"===e||this._default_config.errorContinue&&"err"===e?(--this._call_index,"err"===e&&this._set_error(n),this._check_call_array()):"err"!==e||this._default_config.errorContinue||(this._call_index=0,this.pArray=[],this._error=new Error("The call chain has reject"),this._check_call_array())}},{key:"_set_error",value:function(t){t||(t=new Error("no message reject")),this._error?Array.isArray(this._error)?this._error.push(t):this._error=[this._error,t]:this._error=t}},{key:"_check_call_array",value:function(){0===this._call_index&&this.pArray.length>0?this._next():0===this._call_index&&0===this.pArray.length&&(this._callback&&(this._zcoil._dataTransToThis(),this._error&&this._default_config.rollback&&this._zcoil._dataTransToThis(this._rollback_data_),this._callback.call(this._zcoil,this._model,this._error),this._error=null,this._call_stack=[]),this._ncoil.pArray.length>0?(this._ncoil._default_config.rollback&&this._ncoil._default_config.saveWithExec&&this._ncoil._save_data(this._zcoil._data),this._ncoil._next()):this._ncoil._wait=!1)}},{key:"_save_data",value:function(t){var e=this;o(t,function(t,n){e._rollback_data_[n]=t})}}]),t}();e.coil=a},function(t,e,n){var r=n(5),o=n(7);t.exports=function(t){return r(t,o(t))}},function(t,e,n){var r=n(6),o=n(22),i=n(2),a=Function.prototype,c=Object.prototype,u=a.toString,f=c.hasOwnProperty,s=u.call(Object);t.exports=function(t){if(!i(t)||"[object Object]"!=r(t))return!1;var e=o(t);if(null===e)return!0;var n=f.call(e,"constructor")&&e.constructor;return"function"==typeof n&&n instanceof n&&u.call(n)==s}},function(t,e,n){var r=n(8),o=n(2);t.exports=function(t){return o(t)&&r(t)}},function(t,e,n){var r=n(43),o=n(54),i=n(46),a=n(53),c=n(45),u=n(31),f=n(1),s=n(96),l=n(17),v=n(35),h=n(3),p=n(95),d=n(29),y=n(42),_=n(94);t.exports=function(t,e,n,b,g,m,x){var j=y(t,n),w=y(e,n),O=x.get(w);if(O)r(t,n,O);else{var S=m?m(j,w,n+"",t,e,x):void 0,I=void 0===S;if(I){var A=f(w),E=!A&&l(w),k=!A&&!E&&d(w);S=w,A||E||k?f(j)?S=j:s(j)?S=a(j):E?(I=!1,S=o(w,!0)):k?(I=!1,S=i(w,!0)):S=[]:p(w)||u(w)?(S=j,u(j)?S=_(j):(!h(j)||b&&v(j))&&(S=c(w))):I=!1}I&&(x.set(w,S),g(S,w,b,m,x),x.delete(w)),r(t,n,S)}}},function(t,e,n){var r=n(26),o=n(43),i=n(44),a=n(97),c=n(3),u=n(7),f=n(42);t.exports=function t(e,n,s,l,v){e!==n&&i(n,function(i,u){if(c(i))v||(v=new r),a(e,n,u,s,t,l,v);else{var h=l?l(f(e,u),i,u+"",e,n,v):void 0;void 0===h&&(h=i),o(e,u,h)}},u)}},function(t,e,n){var r=n(98),o=n(58)(function(t,e,n){r(t,e,n)});t.exports=o},function(t,e,n){var r=n(34);t.exports=function(t){return"function"==typeof t?t:r}},function(t,e){t.exports=function(t){return function(e,n,r){for(var o=-1,i=Object(e),a=r(e),c=a.length;c--;){var u=a[t?c:++o];if(!1===n(i[u],u,i))break}return e}}},function(t,e,n){var r=n(12),o=n(2);t.exports=function(t){return o(t)&&"[object Set]"==r(t)}},function(t,e,n){var r=n(102),o=n(28),i=n(27),a=i&&i.isSet,c=a?o(a):r;t.exports=c},function(t,e,n){var r=n(12),o=n(2);t.exports=function(t){return o(t)&&"[object Map]"==r(t)}},function(t,e,n){var r=n(104),o=n(28),i=n(27),a=i&&i.isMap,c=a?o(a):r;t.exports=c},function(t,e,n){var r=n(3),o=Object.create,i=function(){function t(){}return function(e){if(!r(e))return{};if(o)return o(e);t.prototype=e;var n=new t;return t.prototype=void 0,n}}();t.exports=i},function(t,e,n){var r=n(10),o=r?r.prototype:void 0,i=o?o.valueOf:void 0;t.exports=function(t){return i?Object(i.call(t)):{}}},function(t,e){var n=/\w*$/;t.exports=function(t){var e=new t.constructor(t.source,n.exec(t));return e.lastIndex=t.lastIndex,e}},function(t,e,n){var r=n(21);t.exports=function(t,e){var n=e?r(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}},function(t,e,n){var r=n(21),o=n(109),i=n(108),a=n(107),c=n(46);t.exports=function(t,e,n){var u=t.constructor;switch(e){case"[object ArrayBuffer]":return r(t);case"[object Boolean]":case"[object Date]":return new u(+t);case"[object DataView]":return o(t,n);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]":return c(t,n);case"[object Map]":return new u;case"[object Number]":case"[object String]":return new u(t);case"[object RegExp]":return i(t);case"[object Set]":return new u;case"[object Symbol]":return a(t)}}},function(t,e){var n=Object.prototype.hasOwnProperty;t.exports=function(t){var e=t.length,r=new t.constructor(e);return e&&"string"==typeof t[0]&&n.call(t,"index")&&(r.index=t.index,r.input=t.input),r}},function(t,e,n){var r=n(4)(n(0),"WeakMap");t.exports=r},function(t,e,n){var r=n(4)(n(0),"Set");t.exports=r},function(t,e,n){var r=n(4)(n(0),"Promise");t.exports=r},function(t,e,n){var r=n(4)(n(0),"DataView");t.exports=r},function(t,e,n){var r=n(48),o=n(51),i=n(7);t.exports=function(t){return r(t,i,o)}},function(t,e,n){var r=n(5),o=n(51);t.exports=function(t,e){return r(t,o(t),e)}},function(t,e){t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,o=0,i=[];++n-1}},function(t,e,n){var r=n(15);t.exports=function(t){var e=this.__data__,n=r(e,t);return n<0?void 0:e[n][1]}},function(t,e,n){var r=n(15),o=Array.prototype.splice;t.exports=function(t){var e=this.__data__,n=r(e,t);return!(n<0||(n==e.length-1?e.pop():o.call(e,n,1),--this.size,0))}},function(t,e){t.exports=function(){this.__data__=[],this.size=0}},function(t,e,n){var r=n(26),o=n(124),i=n(37),a=n(123),c=n(122),u=n(54),f=n(53),s=n(119),l=n(117),v=n(49),h=n(116),p=n(12),d=n(111),y=n(110),_=n(45),b=n(1),g=n(17),m=n(105),x=n(3),j=n(103),w=n(18),O="[object Arguments]",S="[object Function]",I="[object Object]",A={};A[O]=A["[object Array]"]=A["[object ArrayBuffer]"]=A["[object DataView]"]=A["[object Boolean]"]=A["[object Date]"]=A["[object Float32Array]"]=A["[object Float64Array]"]=A["[object Int8Array]"]=A["[object Int16Array]"]=A["[object Int32Array]"]=A["[object Map]"]=A["[object Number]"]=A[I]=A["[object RegExp]"]=A["[object Set]"]=A["[object String]"]=A["[object Symbol]"]=A["[object Uint8Array]"]=A["[object Uint8ClampedArray]"]=A["[object Uint16Array]"]=A["[object Uint32Array]"]=!0,A["[object Error]"]=A[S]=A["[object WeakMap]"]=!1,t.exports=function t(e,n,E,k,T,z){var N,P=1&n,D=2&n,R=4&n;if(E&&(N=T?E(e,k,T,z):E(e)),void 0!==N)return N;if(!x(e))return e;var B=b(e);if(B){if(N=d(e),!P)return f(e,N)}else{var C=p(e),F=C==S||"[object GeneratorFunction]"==C;if(g(e))return u(e,P);if(C==I||C==O||F&&!T){if(N=D||F?{}:_(e),!P)return D?l(e,c(N,e)):s(e,a(N,e))}else{if(!A[C])return T?e:{};N=y(e,C,P)}}z||(z=new r);var M=z.get(e);if(M)return M;if(z.set(e,N),j(e))return e.forEach(function(r){N.add(t(r,n,E,r,e,z))}),N;if(m(e))return e.forEach(function(r,o){N.set(o,t(r,n,E,o,e,z))}),N;var L=R?D?h:v:D?keysIn:w,$=B?void 0:L(e);return o($||e,function(r,o){$&&(r=e[o=r]),i(N,o,t(r,n,E,o,e,z))}),N}},function(t,e,n){var r=n(56)(Object.keys,Object);t.exports=r},function(t,e,n){var r=n(19),o=n(148),i=Object.prototype.hasOwnProperty;t.exports=function(t){if(!r(t))return o(t);var e=[];for(var n in Object(t))i.call(t,n)&&"constructor"!=n&&e.push(n);return e}},function(t,e,n){var r=n(6),o=n(33),i=n(2),a={};a["[object Float32Array]"]=a["[object Float64Array]"]=a["[object Int8Array]"]=a["[object Int16Array]"]=a["[object Int32Array]"]=a["[object Uint8Array]"]=a["[object Uint8ClampedArray]"]=a["[object Uint16Array]"]=a["[object Uint32Array]"]=!0,a["[object Arguments]"]=a["[object Array]"]=a["[object ArrayBuffer]"]=a["[object Boolean]"]=a["[object DataView]"]=a["[object Date]"]=a["[object Error]"]=a["[object Function]"]=a["[object Map]"]=a["[object Number]"]=a["[object Object]"]=a["[object RegExp]"]=a["[object Set]"]=a["[object String]"]=a["[object WeakMap]"]=!1,t.exports=function(t){return i(t)&&o(t.length)&&!!a[r(t)]}},function(t,e){t.exports=function(){return!1}},function(t,e,n){var r=n(6),o=n(2);t.exports=function(t){return o(t)&&"[object Arguments]"==r(t)}},function(t,e){t.exports=function(t,e){for(var n=-1,r=Array(t);++n0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}},function(t,e){t.exports=function(t){return function(){return t}}},function(t,e,n){var r=n(156),o=n(62),i=n(34),a=o?function(t,e){return o(t,"toString",{configurable:!0,enumerable:!1,value:r(e),writable:!0})}:i;t.exports=a},function(t,e,n){var r=n(157),o=n(155)(r);t.exports=o},function(t,e){t.exports=function(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}},function(t,e,n){var r=n(159),o=Math.max;t.exports=function(t,e,n){return e=o(void 0===e?t.length-1:e,0),function(){for(var i=arguments,a=-1,c=o(i.length-e,0),u=Array(c);++a0&&this._watch_array.forEach(function(e){e._on_data_change(t)})}},{key:"_serialize",value:function(){var t=this;this._config&&this._config.name&&this._config.localStorage&&this.$watch(function(e,n){e&&(v.serializeData(t._config.name,t._data).catch(function(){throw new Error("new zcoil(); serialize error")}),v.serializeData("_"+t._config.name+"_deadline",u.getTimestamp()+1e3*t._config.deadline).catch(function(){throw new Error("new zcoil(); serialize error")}))})}},{key:"_dataTransToThis",value:function(t){var e=this;a(this._data,function(n,r){t?e._data[r]=e[r]=n=e._model[r]=t[r]:e._model[r]?e._data[r]=e[r]=n=e._model[r]:e._data[r]=e[r]=e._model[r]=n}),this._watch_array.length>0&&this._watch_each_call(this._data)}}],[{key:"$assign",value:function(){for(var e=arguments.length,n=Array(e),r=0;r