React Native学习笔记(六)

本文介绍了JavaScript中Promise以及async函数的使用。

本文首发:http://yuweiguocn.github.io/

《送友人》
青山横北郭,白水绕东城。
此地一为别,孤蓬万里征。
浮云游子意,落日故人情。
挥手自兹去,萧萧班马鸣。
—唐,李白

Promise简介

Promise 是异步编程的一种解决方案。ES6原生提供 Promise 对象。Promise 对象代表一个异步操作,有三种状态: Pending(进行中)、 Resolved(已完成,又称Fulfilled)和 Rejected(已失败)。

Promise 有两个特点:

  • 对象的状态不受外界影响。 Promise 对象代表一个异步操作,有三种状态: Pending (进行中)、 Resolved (已完成,又称Fulfilled)和 Rejected (已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。 Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected 。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。

Promise 也有一些缺点。首先,无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数, Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

Promise简单使用

使用 new 创建一个 promise 对象,Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是resolve 函数和 reject 函数:

var promise = new Promise(function(resolve, reject) {
    // 异步处理
    var result = getAsyncResult();
    // 处理结束后、调用resolve 或 reject
    resolve(result); 
    // or reject(new Error("出错了"));
});

resolve 函数的作用是,将Promise对象的状态从Pending变为Resolved,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去; reject 函数的作用是,将Promise对象的状态从Pending变为Rejected,在异步操作失败时调用,并将异步操作报出的异常,作为参数传递出去。

Promise 实例生成以后,可以用 then 方法分别指定 Resolved 状态和 Reject 状态的回调函数。

promise.then(function(value) {
    // success
    console.log(value);
}, function(error) {
    // failure
    console.log(error);
});

then 方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是 Promise 对象的状态变为 Reject 时调用。其中,第二个函数是可选的。这两个函数都接受 Promise 对象传出的值作为参数。当不使用第二个回调函数时可以使用 catch 处理异常:

promise.then(function(value) {
    // success
    console.log(value);
}).catch(function(error) {
    // failure
    console.log(error);
});

使用 then 和 catch 处理异常的区别:

  • 使用 promise.then(onFulfilled, onRejected) 的话在 onFulfilled 中发生异常的话,在 onRejected 中是捕获不到这个异常的。
  • promise.then(onFulfilled).catch(onRejected) 的情况下 then 中产生的异常能在 .catch 中捕获。

所以我们应该总是使用 catch 处理异常

Promise.resolve

静态方法 Promise.resolve(value) 可以认为是 new Promise() 方法的快捷方式。比如 Promise.resolve(42); 可以认为是以下代码的语法糖。

new Promise(function(resolve){
    resolve(42);
});

Promise.reject

Promise.reject(error) 是和 Promise.resolve(value) 类似的静态方法。比如 Promise.reject(new Error("出错了")) 就是下面代码的语法糖形式。

new Promise(function(resolve,reject){
    reject(new Error("出错了"));
});

then的链式调用

从代码上乍一看, promise.then(...).catch(...) 像是针对最初的 promise 对象进行了一连串的方法链调用。然而实际上不管是 then 还是 catch 方法调用,都返回了一个新的 promise 对象。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。

var promise = Promise.resolve(5);
promise.then(function taskA(value){
    console.log(value);
    return Promise.resolve("taskA");
}).then(function taskB(value){
    console.log(value);
}).catch(function onRejected(error){
    console.log(error);
});

// 打印输出:
5
taskA

上面的代码使用 then 方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。每个方法中 return 的值不仅只局限于字符串或者数值类型,也可以是对象或者 promise 对象等复杂类型。return 的值会由 Promise.resolve(return的返回值); 进行相应的包装处理,因此不管回调函数中会返回一个什么样的值,最终 then 的结果都是返回一个新创建的 promise 对象。

var promise = Promise.resolve(5);
promise.then(function (value){
    return Promise.reject("error in then");
}).then(
    value => console.log(value)
).catch(
    e => console.log(e)
);

//打印输出:
error in then

前面所有 promise 对象包括一个 promise 和两个 then 产生的 promise 对象发生的异常都会被最后一个 catch 捕获。但如果前面的 promise 发生异常后,后面的 then 方法不会被调用,而是直接调用最后的 catch 方法。上述代码使用了ES6中箭头函数,使代码更简洁,不清楚的同学请移步本系列的第一篇文章。

Promise.all

Promise.all 接收一个 promise 对象的数组作为参数,数组中的 promise 将会同时执行,当这个数组里的所有 promise 对象全部变为 fulfilled 状态的时候,它才会去调用 then 方法,并且会将返回值组成一个数组传递给 then 方法。

var p1 = Promise.resolve(1);
var p2 = Promise.resolve(2);
var p3 = Promise.resolve(3);

Promise.all([p1,p2,p3])
.then( 
    results => console.log(results)
).catch(
    e => console.log(e)
);

//打印输出:
1,2,3

如果有变为 rejected 状态的 promise 对象,则立即会将第一个被 reject 的实例的返回值传递给 catch 方法。

var p1 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        console.log("p1 execute");
        resolve(1);
    }, 100);
});
var p2 = Promise.reject("error");
var p3 = Promise.resolve(3);

Promise.all([p1,p2,p3])
.then( 
    results => console.log(results)
).catch(
    e => console.log(e)
);

//打印输出:
error
p1 execute

Promise.race

它的使用方法和 Promise.all 一样,接收一个 promise 对象数组为参数。Promise.all 在接收到的所有的对象promise都变为 FulFilled 或者 Rejected 状态之后才会继续进行后面的处理, 与之相对的是 Promise.race 只要有一个 promise 对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。

var p1 = Promise.resolve(1);
var p2 = Promise.resolve(2);
var p3 = Promise.resolve(3);

Promise.race([p1,p2,p3])
.then( 
    result => console.log(result)
).catch(
    e => console.log(e)
);

//打印输出:
1

async 函数

ES7提供了 async 函数,使得异步操作变得更加方便。async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。正常情况下, await 命令后面是一个 Promise 对象。如果不是,会被转成一个立即 resolve 的 Promise 对象。

function f() {
  return new Promise((resolve) => {
    setTimeout(resolve("async result"), 200);
  });
}
async function asyncHello() {
  var p = await f();
  console.log(p);
  return "async finish";
}
asyncHello().then(value => console.log(value));

//打印输出:
async result
async finish

查看React Native学习笔记相关文章

参考

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

推荐阅读更多精彩内容

  • Promise 对象 Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函...
    neromous阅读 8,556评论 1 56
  • Promiese 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,语法上说,Pr...
    雨飞飞雨阅读 3,329评论 0 19
  • 本文适用的读者 本文写给有一定Promise使用经验的人,如果你还没有使用过Promise,这篇文章可能不适合你,...
    HZ充电大喵阅读 7,242评论 6 19
  • 1. Promise 的含义 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个...
    ROBIN2015阅读 450评论 0 0
  • 从2011年1月21日腾讯推出微信聊开工具到现在,据数据统计注册人数大概已经在7亿人左右。注册公众号大约有2200...
    天使之约阅读 227评论 0 0