从同步到异步 - iOS转RN最需转变的思路

说是iOS转React Native,不如说是iOS转JavaScript最需要转变的思路。

本质上来说JavaScript是单线程语言;同时,可能因为它是为网络而生,需要高频度地向服务器读取数据;再者,可能因为它所在的客户端——浏览器——的执行效率并不高;因此,它采取了大量的异步化操作。例如,要装载图片,需要有一个异步读取图片的过程;要读取文件/数据库,也必须异步读取;可能最令iOS程序员发指的是,如果要使用原生的iOS模块,那么必然会要用异取读取。

所以,原来简单的iOS程序,就会变得支离破碎。就拿读文件来说,在iOS程序中,你只需要在一个模块中按顺序写下来就好:

1)获得文件路径
2)打开文件,读取文件内容(若读取时间长,顶多来一个UI转圈界面展示)
3)使用文件内容

转到RN中呢,你需要

1)获得文件路径
2)开一个子线程去读文件
3)准备一个回调(callback)函数,等待子线程读取后再返回

看起来好像没有什么区别,但是,由于JS是单线程函数,你还不能在主线程中单纯等待返回。真实的情况是,主线程执行完了,才会去执行子线程。因此,一个简单的读取文件的过程,就不得不写成好像从服务器异步读取数据一样麻烦。

单是读取文件也罢了,若是你写了一个iOS原生模块,是各种工具函数的集合,然后会在RN模块中反复调用。那么,你就需要在等待一个函数返回之后,再调用另一个函数,于是,在多次调用之后,你发现已陷入到传说中的“回调地狱”!

说实话,这是我从iOS编程转向RN的过程中,最不习惯的一道坎!比起编程环境搭建,比起各种模块的调用方式,这个思路上的转变最让人闹心。

最后,还是找到一些相对简单的解决方法。以下这篇文章给出了最有用的一种方法:
http://blog.csdn.net/kunshan_shenbin/article/details/40425143

简单说,就是用特定的语法方式,让编写代码的过程,变得不再大括号套小括号。以下是这种方法使用的简单流程。

1.在文件头引入Generator、以及next控制函数的工具性代码

// 当前的 Generator
let activeGenerator;

// 处理 g.next() 功能
function gNext() {
    return function(err, data) {
    if(err) {
        throw err;
    }
    //  g.next(),并把回调函数的结果作为参数传递给 yield
    activeGenerator.next(data)
  }
}

// 控制工具
function gQueue(generatorFunc) {
  activeGenerator= generatorFunc(gNext());
  activeGenerator.next();
}

2.异步调用的时候使用这种语法开头

  // 该语句实际产生了一个generator函数,并定义了其中的next操作
   gQueue(function * flow(next) {

“flow”这个名字是随便取的,这里表示它是一个流程控制工具,该名字不会被再次调用。接下来,我们在gQueue中,就能大胆地像写同步语法一样,使用异步调用了:

        let result1 = yield (callBack => {
            someModule.someFunc1(var1, var2..., callBack);
        })(next);

        // 以下语句会在result1获得值后继续执行
        let result2 = yield (callBack => {
            someModule.someFunc2(result, var2..., callBack);
        })(next);

实际上,由于generator函数的特性,每次.next()调用,都会来到新的一条yield语句。然后,该函数所在线程会暂停,开始调用yield语句中的匿名函数。在匿名函数中,我们放置了自己所想要调用的异步操作:someModule.someFunc。

之后的方式非常巧妙,注意,上述匿名函数所使用的形参callBack,在调用的时候,被实参 next 替代。因此,callBack返回,实际上是调用了 next 函数。而根据最前面的工具定义,next 对应的是 gNext() 函数【JS的语法这个地方有点绕,需要多看几遍】,因此,callBack函数中,定义的第一个参数 error 用来描述返回结果是否有误,而第二个参数data,则被当成返回值传给了yield。那么,我们的 result 就获得了这个data值。

更巧妙的是,当 g.next(data)除了返回data值,实质上还执行了一次.next操作。那么,generator函数所有线程将继续执行,这样就保证了后续语句立刻会在返回后运行。实现了看似“同步连续执行”的效果。

如果对以上机制仍感模糊,阮一峰老师的这篇文章值得推荐:Generator 函数的语法

3.回调函数callBack的特殊规则

根据以上机制,要正确地使用该方法,必须对我们使用的callBack使用特定的返回机制。callBack的第一个参数 error 必须用来描述返回结果是否有误,而第二个参数data则用于返回真正需要的数据。假如你返回的数据有多个,那么必须打包成一个数据,然后在返回值里再做反向解析。以下是这一callBack机制的正确使用方式:

    function someFunction(var1, var2, callback) {
        // some operation,最后得到两个值要返回
        let result1 = ...;
        let result2 = ...;
        callback(null, [result1, result2]);
    }

最后的语句中,偷懒把错误值定成了null,待返回的两个值,包装成一个数组作为data返回过去了。那么后面调用时,获得这个两个值,就必须分别从结果中以数组方式解析。

4.其它

这篇文章只是描述了异步调用的一个最大障碍。相关的问题还有 setTimeout 函数的应用,以及针对异步模块调用的监听等技术方案,将来有空再来细述。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,884评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,212评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,351评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,412评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,438评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,127评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,714评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,636评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,173评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,264评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,402评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,073评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,763评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,253评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,382评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,749评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,403评论 2 358

推荐阅读更多精彩内容