UNPKG

jsdk-offical

Version:

JSDK is the most comprehensive TypeScript framework, like JDK.

333 lines (281 loc) 10.2 kB
## 控制台 JSDK用工具类<b>JS.util.Konsole</b>取代了直接使用console对象。 在控制台打印带样式的文本: ```javascript Konsole.text(`Welcome to JSDK ${JS.version}`, `font-weight:bold;color:blue;text-shadow:1px 1px 1px #D2E9FF;`); ``` 在控制台打印多个数据: ```javascript Konsole.print(1, 2, 3); ``` 清空控制台的输出信息: ```javascript Konsole.clear(); ``` ## 日志 ### 使用日志类 在需要日志输出的地方,实例化一个日志类: ```javascript let myLogger = new Log('My Logger', LogLevel.INFO); //设置输出级别为INFO ``` 你也可以将某个包名或某个类名作为日志名。用来标示出该日志类应该被此包或此类使用: ```javascript let logger1 = new Log('JS.data.*'); let logger2 = new Log(Button.class.name); ``` 现在,可以使用日志对象来输出日志了: ```javascript myLogger.trace('this is trace'); myLogger.debug('this is debug'); myLogger.info('this is info'); myLogger.warn('this is warn'); myLogger.error('this is error'); ``` ### 日志级别 可使用的日志级别共5级,再加上ALL/OFF两个控制用级别,一共是7级: ```javascript export enum LogLevel { ALL = 6, TRACE = 5, DEBUG = 4, INFO = 3, WARN = 2, ERROR = 1, OFF = 0 } ``` * *ALL表示输出全部;OFF表示无任何输出* 只有当某条信息的级别小于等于日志对象所规定的输出级别时,这条信息才会被输出。<br> 比如,日志对象的输出级别设置为WARN;某条信息的级别为INFO则该条信息不会输出至控制台: ```javascript let myLogger = new Log('My Logger', LogLevel.WARN); //输出级别为WARN myLogger.info('info'); //信息级别高出WARN, 控制台不会打印 myLogger.error('error'); //信息级别低于WARN, 控制台会打印: error ``` ### 输出模式 缺省情况下,日志信息直接输出到控制台。JSDK也允许你来定义输出到其他地方。 例如,我们需要将日志提交到服务器而不是控制台。<br> 第一步:先定义一个新类<code>AjaxAppender</code> ```javascript export class AjaxAppender implements LogAppender { private name = ''; constructor(name: string){ this.name = name; } public log(level: LogLevel.TRACE | LogLevel.DEBUG | LogLevel.INFO | LogLevel.WARN | LogLevel.ERROR, ...data: any[]) { Http.send({ url: 'xxxx', data: { name: this.name, values: Jsons.stringify(data) } }) } } ``` 第二步:用<code>AjaxAppender</code>来实例化日志对象 ```javascript let myLogger = new Log('My Logger', LogLevel.INFO, AjaxAppender); ``` 当我们使用新的myLogger对象时,输入的日志就提交至服务器了。 ## 错误处理 JSDK提供了<b>JS.lang.JSError</b>类作为自定义Error的父类(继承自原生的Error类)。 ### 预定义Error JSDK预定义了7个Error类,继承自JSError类。你可以直接使用这些Error,它们分别是: ```text RefusedError NotFoundError ArithmeticError ArgumentError StateError NetworkError TimeoutError ``` * *使用类JS.util.Errors,你可以更快访问到全部Error类:包括原生Error类和JSDK的预定义Error类。* ### 自定义Error 举例,定义一个名为MyError的新类: ```javascript export class MyError extends JSError { } ``` 然后就可以使用: ```javascript throw new MyError('xxxxx'); ``` ### 正确使用异常 与Java不同的是,JS语法中并没有捕获式异常和运行时异常的区分,都属于运行时异常。<br> 由于JS的错误异常可以在代码中随时随地抛出而无需编译前声明,所以我们应该遵循一些好的<b>异常处理原则</b>: > 1. 必须中止的错误发生时,请抛出异常;抛出前应考虑用高层级的异常类来包装原有的低层级的异常;同时应该在jsdoc中备注何时会发生何种异常,以便调用者注意。 > > 2. 必须保证健壮运行的代码应该捕获并屏蔽异常,不要再向上抛出异常。 > > 3. 非必要时尽量不抛出异常;方法可以尽量设计成以返回nullfalse表示执行失败,同时考虑日志打印异常上下文信息以方便调试。 ## 国际化 JSDK提供工具类<b>JS.util.I18N</b>来管理国际化资源。 ### 资源的加载 I18N类允许以两种方式加载JSON格式的资源:本地的资源数据或远程的资源文件。 <b>1. 加载本地的资源数据</b> ```javascript let i18n = new I18N('zh-CN').set({ 'zh': { k1: '中文' }, 'zh-CN': {//将加载这块数据 k1: '中文,中国' }, 'CN': { k1: '中国' } }); ``` <code>set</code>方法会以下顺序去查找资源数据中的键(假设当前时区为"zh-CN"),找到后加载数据: <p class="warn"> zh_CN<br> zh </p> * *当前键不存在则自动查找下一级键。如果最终所有这些键都不存在,则I8N类会自动装载整个JSON数据。* <b>2. 加载远程的资源文件</b> ```javascript let i18n = new I18N(); //缺省为系统时区:System.info().locale i18n.load('http://mydomain/xxx.yyy', 'zh-CN'); //当前时区为zh-CN ``` <code>xxx.yyy</code>文件是一个JSON格式的资源文件: ```text { "k1": "中文,中国" } ``` <code>load</code>方法会以下顺序去依次查找资源文件名(假设当前时区为"zh-CN"),找到后以Ajax方式加载数据: <p class="warn"> xxx_zh_CN.yyy<br> xxx_zh.yyy<br> xxx.yyy </p> * *当前文件不存在则自动查找下一级文件。如果最终所有这些文件都不存在,则会打印错误日志:未找到任何可用的资源文件。* ### 资源的使用 ```javascript i18n.get('k1'); //Read the value of "k1" in current locale i18n.get(); //Read all key-value pairs in current locale ``` ## 事件总线 JSDK提供了事件总线类<b>JS.util.EventBus</b>来管理事件的订阅与发布。 我们在需要使用事件管理器的地方,初始化一个EventBus对象: ```javascript let bus = new EventBus(...); ``` ### 事件订阅 事件的监听方在事件发生前需要订阅事件(假设事件名为"ring"): ```javascript bus.on('ring', (e:Event, a, b)=>{ Konsole.print(a, b); //print 1 and 2 return false //返回False将阻止事件的继续传播 }) ``` ### 事件发布 事件的触发方在事件发生时需要发布事件: ```javascript bus.fire('ring', [1,2]); ``` ## DOM与BOM JSDK对<code>HTMLElement</code>对象的原型链进行了扩展,增加了一些仿jQuery的方法。方便用户无须加载jquery库就可以完成基本的DOM操作。 扩展方法如下: ```javascript interface HTMLElement { attr(key:string):string; attr(key:string, val:string):this; html():string; html(html:string):this; addClass(cls:string):this; removeClass(cls:string):this; hasClass(cls:string):boolean; toggleClass(cls:string, isAdd?:boolean):this; on(type:string, fn:(this:HTMLElement, e:Event)=>boolean|void, once?:boolean):this; off(type?:string, fn?:(this:HTMLElement, e:Event)=>boolean|void):this; find(selector:string):HTMLElement; findAll(selector:string):NodeListOf<HTMLElement>; ...... } ``` * *你可以在DOM对象上直接使用上述方法。* 同时,JSDK对<code>Window</code>对象的原型链进行了扩展,增加了两个方法以取代旧方法: addListener/removeListener。 ```javascript interface Window { on(type:string, fn:(this:Window, e:Event)=>boolean|void, once?:boolean):this; off(type?:string, fn?:(this:Window, e:Event)=>boolean|void):this; } ``` * *你可以在Window对象上直接使用上述方法。* 另外,工具类<b>JS.util.Dom</b>/<b>JS.util.Bom</b>提供了很多有用方法。 ```javascript Bom.ready(() => { //$1 === Dom.S1 $1('btn1').on('click',()=>{ //do you want }) }) ``` * *更多方法请参看API文档* <p class="tip"> 注意: <br><br> 请不要在线程代码中使用HTMLElement的扩展方法以及JS.util.Dom类,也不要尝试执行任何与DOM相关的API,否则会直接导致线程脚本错误。因为WebWorker规范禁止在线程代码中读写DOM。 </p> ## Promise助手 HTML5提供了 <b>Promise</b> 来更好的支持异步回调式编程。 例如,我们实例化一个 <b>Promise</b> 对象: ```javascript let p = new Promise<T>((resolve, reject) => { ... resolve(1); ... reject(2); }) ``` 上述代码显得不够简明且产生了硬值依赖,JSDK提供了助手类 <b>JS.util.Promises</b> 可以实现更好的写法: ```javascript let p = Promises.create(function(a, b){ ... this.resolve(a); ... this.reject(b); }, 1, 2) ``` ### 计划与计划队列 JSDK将返回Promise类型的函数定义为 <b>PromisePlan</b>: ```javascript export type PromisePlan<T> = (...args:any[])=>Promise<T>; ``` 而将一组 <b>PromisePlan</b> 定义为 <b>PromisePlans</b> 计划队列: ```javascript export type PromisePlans<T> = Array<PromisePlan<T>>; ``` ### 计划队列的执行 一个异步计划的执行很简单,一组异步计划的执行与结果返回才是难点。<br> 原生的 <b>Promise</b> 类已提供两种队列执行模式: * <b>all</b>: 并行执行,所有异步执行都完成才返回。 * <b>race</b>: 并行执行,任一个异步执行完成就返回。 现实情况下,我们常常需要第三种执行模式: * <b>order</b>: 串行执行,执行完一个异步才能执行下一个异步。最后一个执行完毕才返回。 <b>Promises</b> 类提供了对以上三种执行模式的支持: ```javascript //PromisePlan a let a = Promises.createPlan<string>(function () { this.resolve('a'); }); //PromisePlan b let b = Promises.createPlan<string>(function (s) { this.resolve(s+'b'); }); //PromisePlan c let c = Promises.createPlan<string>(function (s) { this.resolve(s+'c'); }); Promises.order([a, b, c]).then((s) => { Konsole.print('The result of order mode = ' + s); }); Promises.all([a, b, c]).then((s) => { Konsole.print('The result of all mode = ' + s); }); Promises.race([a, b, c]).then((s) => { Konsole.print('The result of race mode = ' + s); }); ```