atomic/zone

Zone 底座:原子函数


Methods

(static) assign(target, source, mode) → {Object}

「标准」Ux.assign

三种模式的拷贝函数,增强原始的Object.assign函数。

  • mode = 0 :直接覆盖,内部调用Object.assign方法。
  • mode = 1 :深度覆盖,不直接覆盖子对象,递归往下,发现同键数据后直接覆盖数据。
  • mode = 2 :深度追加,不直接覆盖子对象,递归往下,同键不存在则追加,出现重复建则直接跳过。
// mode = 0(默认模式)
const target = {
    name: "mode"
};
const source = {
    email: "lang.yu@hpe.com"
};

// 等价于 Object.assign(target,source);
const combine = Ux.assign(target,source);

// mode = 1 和 mode = 2 的模式则参考实际使用。

实际上mode为1或2的场景在很多实战场景中有所使用,这两种模式不会直接覆盖子对象(包括嵌套对象),而是通过比对的方式执行覆盖追加(同名跳过)操作,实现深度合并。

Parameters:
Name Type Default Description
target Object

拷贝目标(副作用修改)

source Object

拷贝源

mode Number 0

模式参数,用于不同的模式:0 = 默认,1 = 深度覆盖,2 = 深度追加

Returns:

合并好的JavaScript对象Object

Type
Object

(static) clone(input) → {any}

「标准」Ux.clone

该函数是一个高频使用函数,内置使用Immutable的API实现对象拷贝,拷贝对象分为以下几种场景:

  1. 普通JS对象:Object/Array,直接调用Immutable.fromJS.toJS的链式调用实现对象拷贝。
  2. DataArray/DataObject:将这两种对象的内部内容拷贝出来,生成Object或Array。
  3. Function:(不拷贝),直接返回原始函数,防止函数拷贝过程中的错误信息。
  4. NodeList:Dom对象由于挂载在HTML元素中,所以不执行拷贝,而是直接返回该Dom引用。
  5. Set:如果是集合,则创建一个新的集合,将元素依次追加到集合中。
  6. Acl数组:对存在权限控制的Array/Object而言,它会包含一个索引之外的__acl属性,该属性存储了Acl的权限属性。
    1. 对Object类型而言,会直接拷贝__acl属性。
    2. 对Array类型,需要独立拷贝__acl属性(Immutable不会复制非索引访问的属性)。

此处的JS应用了原型链,由于Array本身是一个Object,所以除了索引以外,可直接追加属性,只是这些属性不作为标准Array元素对待。

// 直接拷贝对象,拷贝过后的对象的任何更改都不会反应到原始对象
const before = {
     name: "Lang"
};
const after = Ux.clone(before);
after.name = "Lang2";
console.info(item,input);

// before 的值依旧是:{ name: "Lang" }
// after 的值为修改后的值 { name: "Lang2" };
Parameters:
Name Type Description
input DataObject | DataArray | Object | Array

传入合法对象,

Returns:

返回拷贝好的 Object

Type
any

(static) connectId(id)

「标准」Ux.connectId

必须在componentDidMount之后才能执行。

使用外围的代码触发onClick操作,点击id相匹配的元素。

Parameters:
Name Type Description
id String

触发id的点击事件。

(static) element(id) → {HTMLElement}

「标准」Ux.element

等价于 document.getElementById 读取HTML元素。

Parameters:
Name Type Description
id String

HTML元素的ID值

Returns:
Type
HTMLElement

(static) immutable(input) → {Map|List}

「标准」Ux.immutable

直接调用 immutable 包中的 Immutable.fromJS 函数,生成 Immutable 对象,该对象包含了很多新的API,如常用的:

  • getIn:可直接使用getIn(["field1","field11"])读取嵌套属性。
  • setIn:可使用setIn(["field1","field11"])设置嵌套属性。
  • contains:高频使用方法,特别是Array模式,当然也可以直接使用ES6中的Set.has来判断。
const item = ["key", "key1"];
const $item = Ux.immutable(item);

console.info($item.contains("key"));
Parameters:
Name Type Description
input Object | Array

输入对象,可以是任意 JavaScript 对象

Returns:

Immutable库中需要使用的专用对象

Type
Map | List

(async, static) parallel(promises, keys) → {Promise.<T>}

「标准」Ux.parallel

并行 Promise 专用函数,每个 Promise 会同时执行最终合并结果,直接构造并行运行结果

  1. 如果不传第二参数,keys 长度为 0,则直接返回 [x] 的 promises 直接结果
  2. 如果传入第二参,keys 长度 > 0,则会返回 {} 的 promises 直接结果

直接并行 []

const promiseArray = [
     promise1,       // 假设返回 {name:"Lang"}
     promise2,       // 假设返回 [1,2]
     promise3        // 假设返回 "3 Promise"
];
Ux.parallel(promiseArray).then(response => {
     // response 数据结构:
     // [
     //      {name, "Lang"},
     //      [1,2],
     //      "3 Promise"
     // ]
});

异构并行 {}

const promiseArray = [
     promise1,       // 假设返回 {name:"Lang"}
     promise2,       // 假设返回 [1,2]
     promise3        // 假设返回 "3 Promise"
];
Ux.parallel(promiseArray, "user", "number").then(response => {
     // response 数据结构:
     // {
     //      "user": {name, "Lang"},
     //      "number": [1,2],
     //      "2": "3 Promise"
     // }
});
Parameters:
Name Type Description
promises Array

一个 Promise 的数组。

keys Array.<String>

一个包含键的数组,用于处理最终返回值专用。

Returns:

返回最终的 Promise

Type
Promise.<T>

(async, static) pass(executor, response) → {Promise.<Any>}

「标准」Ux.pass

基本介绍

函数异步返回安全处理,直接执行 executor 函数,根据其返回值做选择:

  • 如果 executor 不是一个函数,则直接返回 promise(response) 封装
  • 如果 executor 是一个执行函数,则直接计算此函数,并根据返回值判断
    • 若返回值是一个 Promise,则直接返回
    • 若返回值不是一个 Promise,则返回 promise(response)
Parameters:
Name Type Description
executor function

传入的函数执行器

response Any

默认返回值

Returns:
Type
Promise.<Any>

(async, static) passion(generator, input) → {Promise.<T>}

「标准」Ux.passion

顺序链接 Promise 专用函数(串行Promise),最终构造成 Monad 链

input -> Monad1 -> out1,
out1 ->  Monad2 -> out2,
out2 ->  Monad3 -> out3,
....

# 最终构造链式结构
Monad1 -> Monad2 -> Monad3 -> ... -> Monadn

执行步骤如下:

  1. 数组中的每一个元素都必须是一个函数生成器(generator),每调用一次会生成这个节点的 Promise
  2. 使用 generator 的目的是保证每个 Promise 都是延迟生成。
  3. 按照流程,第一个 generator 生成了 Promise 过后,会使用 then 的方式继续往下直到最后一个执行完成。
Parameters:
Name Type Description
generator Array

构造每一个节点的 Promise 的专用函数

input any

第一个节点的 Promise 的输入参数

Returns:

返回最终的 Promise 信息

Type
Promise.<T>

(static) pipe(argumentsopt)

「引擎」Ux.pipe

输入可变长度参数相关信息,暂时支持:

  1. 长度为1:必须输入 reference(React中的Component)

该方法主要位于 then 的函数链执行,执行过后会更新 React 组件中的状态,该方法有一定的副作用,因为它会执行一次setState, 所以真正使用这个函数时通常放在整个链式结构的尾部,而尾部执行操作可让系统处于最终的加载完成的状态。

【巧】技巧代码

旧代码


const reference = "从外置传入的 reference ";
Ux.ajaxGet("/api/pipe").then(state => {
    reference.setState(state);
    return Ux.promise(state);
});

新代码


// 使用 pipe 过后的改动代码
const reference = "从外置传入的 reference ";
Ux.ajaxGet("/api/pipe").then(Ux.pipe(reference));

Parameters:
Name Type Attributes Description
arguments arguments <optional>

可变长度参数

(static) pipeOr()

「引擎」Ux.pipeOr

(static) prevent(event) → {Object}

「标准」Ux.prevent

特殊二义性函数「Ambiguity」,该函数的输入会有两种类型,其实第一种方式应用特别多:

  • 如果传入的是HTML中的native本地函数,通常在Button的onClick中会被传入。
  • 如果传入的是Object数据,那么直接返回该Object数据。

这个函数读取数据有另外的一个API来实现ambEvent,所以这里只是为了执行单纯的方法,它执行的核心代码为event.preventDefault()

     // 绑定事件
     const onClick = (event) => {
         Ux.prevent(event);
     }
     // 直接传入参数
     const onForm = (params = {}) => {
         const request = Ux.prevent(params);
     }
Parameters:
Name Type Description
event Event | Object

传入事件或对象

Returns:

返回对象信息

Type
Object

(async, static) promise(argumentsopt) → {Promise.<T>}

「标准」Ux.promise

多义性方法,用于返回不同结果的 Promise,多用于函数链中,该方法只对 1,2,3 的长度有效, 不在这个长度范围内时会直接返回 Promise.reject 的异常信息。

  1. 长度为1,直接返回new Promise,将传入对象封装成 Promise 返回,同步转异步。
  2. 长度为2,使用 Supplier 和第二参直接生成 Promise 返回(延迟异步,同步转异步)。
  3. 长度为3,一般用于 Monad 函数链,通常在状态迁移中处理。

长度1

const user = {
    username: "Lang Yu"
};
const promise = Ux.promise(user);

长度2

const supplier = (params = {}) => {

     // 构造新的 Promise
     return Ux.ajaxGet("/api/test/:key", params);
};
const promise = Ux.promise(supplier, {key:"user.id"});

长度3

【巧】技巧代码

旧代码


const state = {};
Ux.ajaxGet("/api/test").then(response => {
    state.$data = response;
    return Ux.promise(state);
})

新代码

const state = {};
Ux.ajaxGet("/api/test")
     .then(response => Ux.promise(state, "$data", response));

使用场景分析

该API提供的方法在整个Promise链中为高频使用方法,他的使用场景有很多,主要是用于修正代码编写风格,使用场景如下:

  1. 直接将一个对象Object/Array等转换成带有异步Promise的数据结构,可直接调用.then的API。
  2. 长度2的使用场景主要用于切面AOP的编程,通常在很多场景中需要执行多维度构造,特别是中间维度的Promise的构造过程。
  3. 长度3的使用场景则通常用于componentDidMount的生命周期中,用于实现挂载流程,如response -> state[key] = response的结构。

该方法存在的意义在于封装了ES6中出现的Promise流程,方便整体调用,Zero Ui的理念是封装第三方,那么第三方的内容封装越多,开发人 员对本身框架的操作程度会越过,其实第一种应用是最常用的,其次是配置化流程中通常使用第二和第三种流程。

Parameters:
Name Type Attributes Description
arguments arguments <optional>

可变长度参数

Returns:

返回最终的 Promise

Type
Promise.<T>

(async, static) ready(state) → {Promise.<T>}

「引擎」Ux.ready

在 Zero Extension 中,内置了配置准备状态,state 中的 $ready,当界面 componentDidMount 执行完成后 会将 $ready 设置成 true,该函数几乎是整个Zero Ui的核心,主要用于设置生命周期的完整。

  1. $ready = false:等待配置完成。
  2. $ready = true:配置执行完成,执行过程可以是异步

旧代码

const key = "1";

Ux.ajaxGet("/api/user",key).then(state => {
     state.$ready = true;
     return Ux.promise(state);
});

新代码

// 使用 ready 过后的改动代码
const key = "1";

Ux.ajaxGet("/api/user",key).then(Ux.ready);

该方法只能作为Monad的中间节点,不可用于尾部节点或开始节点,只能处于函数链的中间环节,Zero中常用的一段代码如:

// 下边代码是常用代码,可设置 $ready = true 来实现准备完成
<Promise>.then(Ux.ready).then(Ux.pipe(this));

在React组件的生命周期中,componentDidMount会执行Ajax的异步操作,到最后设置$ready=true的标识来表示回调 完成,而这种回调完成刚好可应用于当前组件,也就是说当$ready=true时,状态加载彻底完成。

Parameters:
Name Type Description
state

处理之前的原始状态信息,函数链上的 Monad

Returns:

返回一个新的 Promise

Type
Promise.<T>

(static) remove(item, keys)

「标准」Ux.remove

从 item 对象删除某些 keys 值

Parameters:
Name Type Description
item Object

输入对象

keys String | Array

二义性Array