用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,登录网站

6

主题

9

帖子

334

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
334
2017-9-25 23:46:31 yalishizhude原创达人 实习版主 楼主 2333
本帖最后由 yalishizhude 于 2017-9-25 23:50 编辑

好的代码通常符合一个特点:高内聚,低耦合。
通俗地说就是用更少地代码完成更多地功能,比如web前端地MVVM框架就是把对DOM的操作和事件监听抽象出来,通过数据绑定来更新数据和视图。
“组件化”的思想也是如此,组件的目的不是简单的代码分割,更重要的是方便代码的复用。
这些都是针对视图层面的优化措施,针对数据层,其实也有方法写出更优秀的代码。
其中一个简单有效的方法就是尽量编写纯函数。
纯函数
什么是纯函数?可以用一个表达式来描述
输入参数x => 执行代码 => 输出结果y
这看起来好像和普通函数也没啥区别,那么它和普通的函数相比,“纯”在哪里?
  • 从输入来看,参数是必传的,而且不能被修改。比如Math.random这类没有参数的函数就不是纯函数。
  • 从执行来看,不能引用外部变量或函数。
  • 从结果来看,执行必有结果,而且输入相同的参数,执行的结果必须相同。
纯函数是将逻辑分离到极致:一段功能单一,逻辑封闭的代码。
思考:function(x) { return 1 } 是不是纯函数?
如果你的代码中使用纯函数,会带来以下好处:
  • 易测试。写过单元测试的前端开发都知道,前端的单元测试是很难写的,其中很大一个原因就是“不纯”的函数太多,一个函数可能既要操作DOM,又要发送ajax请求,还可能引用了不知名的全局变量…AngularJS在官方文档中就直接指出有些耦合性高的代码是难以测试的,所以这也是近些年MVVM框架流行的原因,框架承担了DOM操作,开发者只负责写逻辑,从而让代码逻辑更清晰。
  • 可复用。 使用Node.js编写服务端的同学对一个词肯定熟悉——“同构”,也就是说,一份js代码可以同时在服务端和浏览器端正常运行,而纯函数是支持同构的。
  • 无副作用。比如多个不纯的函数同时修改一个变量(或操作一个DOM元素),再加上异步等情况,这样就很容易引起冲突。而纯函数既不修改入参也不修改外部变量,所以完全不用担心。
RxJS
符合纯函数特点的第三方开源库有非常著名的underscore和lodash,以及更加强大的RxJS。
RxJS是微软推出的ReactiveX系列(RxJava,Rx.NET,RxScala,RxSwift等)中的一员,目前Github上star数已经超过17k。
它可以用来优雅地处理异步和事件。主要通过它的核心类型 Observable,以及强大的操作符 (map、filter、reduce、every等,其中大部分都是纯函数)来实现。
官方给它最直白的定义是
可以把 RxJS 当做是用来处理事件的 Lodash 。
来一段官方的代码体验一下:

[JavaScript] 纯文本查看 复制代码
// 使用普通的 JavaScript 控制按钮一秒钟内只允许点击一次
var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', () => {
  if (Date.now() - lastClick >= rate) {
    console.log(`Clicked ${++count} times`);
    lastClick = Date.now();
  }
});

// 使用Rx.js实现
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
  .throttleTime(1000)
  .scan(count => count + 1, 0)
  .subscribe(count => console.log(`Clicked ${count} times`));
```

使用RxJS的代码消除了一些中间变量,使用操作符来分步执行逻辑,可读性更强、耦合性更低,更方便测试和修改。
关于RxJS更详细介绍在以后的文章中再叙,本文先谈一谈它的应用。关于RxJS在web端和node.js服务端的应用都不乏文章,所以这一次突破常规,来讲一讲在微信小程序(以下简称“小程序”)开发中的使用。
小程序
直接在小程序中使用RxJS是会报错的,所以我建立了一个开源项目来解决这个问题:RxWX项目地址:https://github.com/yalishizhude/RxJS)。
封装了两个js文件。
  • Rx.js。对Rx.js进行了一些修改使其能在小程序中运行。
  • RxWX.js。基于Rx.js对微信的api进行了封装,调用同名API不再使用回调,而是返回Observalbe对象。
安装
提供两种安装途径
Github
可以直接下载项目,将根目录的Rx.js和RxWX.js复制到小程序项目中,也可以访问该网址复制粘贴这两个文件内容。
npm
npm i rxjs-wx
将node_modules/rxjs-wx目录下的Rx.js和RxWX.js复制到小程序项目中。
使用
小程序的API大多数都不是按照纯函数的思想设计的,把返回结果赋值给入参的success、fail、complete属性。
在逻辑简单复杂的情况下很容堕入“回调地狱”,而且同步和异步的接口调用方式也不一致。而使用RxJS就可以解决这些问题,下面来看几个例子。
处理回调
假设有这样一个需求,先通过wx.getUserInfo获取用户信息,然后传给后端服务获取该用户其它信息,显示在页面上。

[JavaScript] 纯文本查看 复制代码
// 普通代码
let self = this
wx.getUserInfo({
  success: (res) => {
    wx.request({
      method: 'GET',
      url: 'xxx/user',
      data: res.userInfo,
      success(r) {
        self.setData({userInfo:r})
      },
      fail(e) {
        self.setData({userInfo:'not found'})
      }
    })
  },
  fail(e) {
    console.error(e)
  }
})

// 使用RxWX
import obs from './RxWX'

obs.getUserInfo()
  .catch(e => console.error(e))
  .switchMap(({ userInfo }) => obs.request({ method: 'GET', url: 'xxx/user', data: user }))
  .subscribe(userInfo => self.setData({ userInfo: r }), e => self.setData({ userInfo: 'not found' }))


处理事件
曾经在开发小程序的时候使用navigator组件碰到一个比较严重的问题:快速多次点击的时候会发生多次页面跳转,跳转完成后需要多次点击“返回”才能退回到原页面。
为了解决这个问题,一般可以手动绑定事件,然后进行一个防抖操作。

[JavaScript] 纯文本查看 复制代码
tap(e) {
  if(!tapping) {
    wx.navigateTo({ url: '../demo/demo' })
    tapping = true
    setTimeout(() => tapping=false, 1000)
  }
}

// 使用RxWX
import obs from './RxWX'

tap(e) {
  obs.navigateTo({ url: '../demo/demo' })
  .debounce(1000)
  .subscribe()
}


其它
RxWX同时还支持wx对象的其它非函数属性,比如:

[JavaScript] 纯文本查看 复制代码
import obs from './RxWX'

console.log(obs.version) 
// {info:"", updateTime:"2017.7.10 19:35:05", version:"1.4.0"}


最后
RxJS和RxWX是第三方库,也是进入纯函数世界的大门,更是一种编写更好代码的思维方式。


评分

参与人数 1原创 +1 浮云 +50 收起 理由
Rolan + 1 + 50 很给力!

查看全部评分

大佬,付个中文的API或教程啊~
x837195936 发表于 2017-9-26 09:59
大佬,付个中文的API或教程啊~

感谢提醒~
发新帖
您需要登录后才可以回帖 登录 | 立即注册