副作用 - ShenYj/ShenYj.github.io GitHub Wiki
在计算机科学中,函数副作用指当调用函数时,除了返回可能的函数值之外,还对主调用函数产生附加的影响。例如修改全局变量(函数外的变量),修改参数,向主调方的终端、管道输出字符或改变外部存储信息等。 在某些情况下函数副作用会给程序设计带来不必要的麻烦,给程序带来十分难以查找的错误,并降低程序的可读性与可移植性。严格的函数式语言要求函数必须无任何副作用,但功能性静态函数本身的目的正是产生某些副作用。在生命科学中,副作用往往带有贬义,但在计算机科学中,副作用有时正是“主要作用”。
以上文字摘自维基百科 纯函数
在 RxSwift 中什么算是副作用?
RxSwift中文手册-食谱 中给了介绍
如果一个函数除了计算返回值以外,还有其他可观测作用,我们就称这个函数拥有附加作用
副作用包括:
- 发起网络请求
- 刷新 UI
- 读写数据库
- 获取位置信息
- 使用蓝牙模块
- 打印输出
- ...
Observable 中的 附加作用
-
Observable 其实是一个函数 (
RxSwift中文手册-食谱
中给出的简化后的代码)// 去除了不相关的范型约束,便于理解 func subscribe(_ observer: Observer) -> Disposable
subscribe
函数就是Observable
, 换句话说Observable
的副作用, 指的就是subscribe
函数里面的副作用
这是文档中的结论,经过 Observable源码探索,我觉得文中这个简化后的函数应该指的是
public protocol ObservableType : ObservableConvertibleType {
/**
Subscribes `observer` to receive events for this sequence.
### Grammar
**Next\* (Error | Completed)?**
* sequences can produce zero or more elements so zero or more `Next` events can be sent to `observer`
* once an `Error` or `Completed` event is sent, the sequence terminates and can't produce any other elements
It is possible that events are sent from different threads, but no two events can be sent concurrently to
`observer`.
### Resource Management
When sequence sends `Complete` or `Error` event all internal resources that compute sequence elements
will be freed.
To cancel production of sequence elements and free resources immediately, call `dispose` on returned
subscription.
- returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources.
*/
func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E
}
对应的应该就是子类 Producer
给出默认实现的那个 subscribe
函数
文中是这么解释 Observable
的附加作用的
-
示例代码
typealias JSON = Any let json: Observable<JSON> = Observable.create { (observer) -> Disposable in let task = URLSession.shared.dataTask(with: ...) { data, _, error in guard error == nil else { observer.onError(error!) return } guard let data = data, let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) else { observer.onError(DataError.cantParseJSON) return } observer.onNext(jsonObject) observer.onCompleted() } task.resume() return Disposables.create { task.cancel() } }
这里的闭包 { (observer) -> Disposable in ... } 可以看作是 subscribe 函数, 这个函数的附加作用就是发起网络请求去获取一个 JSON。 所以 let json: Observable<JSON> 的 附加作用 也是发起网络请求去获取一个 JSON。
最初看到这段描述的时候,感觉有点矛盾
- 前面提到
subscribe
函数就是Observable
- 这里说
create
的闭包{ (observer) -> Disposable in ... }
是Observable
在 Observable源码探索 这篇笔记中可以了解到
-
创建序列时
create
的闭包是被AnonymousObservable
保存起来,保存的字段是let subscribeHandler: SubscribeHandler
typealias SubscribeHandler = (AnyObserver<Element>) -> Disposable
- 这么一看和
{ (observer) -> Disposable in ... }
闭包中的闭包参数
对的上
笔记中源码对应的是
_subscribeHandler
, 2019年12月20日以前不少命名前面都有下划线,后去掉了,对应的是 Rx 6.0版本
所以我感觉是不是指 { (observer) -> Disposable in ... }
闭包中的 闭包参数
呢,而大闭包内的 ...
部分才是副作用?