浅谈Promise对象在ReactNative中的使用
下面开始:
写在前面
假设现在一个日常开发会遇到这样一个需求:多个接口异步请求,第二个接口依赖于第一个
接口执行完毕之后才能利用数据进行一系列操作。一般会这样写:
A.fetchData({url: 'http://......',success: function (data) {A.fetchData({// 要在第一个请求成功后才可以执行下一步url: 'http://......',success: function (data) {// ......}});}});
这样写没问题,但是有两个缺点:
1、当有多个操作的时候,会导致多个回调函数嵌套,不够美观
2、如果有几个操作没有前后顺序之分时,例如上面的后一个请求不依赖与前一个请求的返回结果的时候,
同样也需要等待上一个操作完成再实行下一个操作。
从ES6开始,Promise对象可以解决上述问题。
什么是Promise对象
一个Promise对象可以理解为一次将要执行的操作,使用了Promise对象之后可以用一种链式调用的方式
来组织代码,让代码更加直观。
resolve和reject
先看代码:
function helloWorld (ready) {return new Promise(function (resolve, reject) {if (ready) {resolve("Hello World!");} else {reject("Good bye!");}});}helloWorld(true).then(function (message) {alert(message);}, function (error) {alert(error);});
上面的代码实现的功能非常简单,helloWord 函数接受一个参数,如果为 true 就打印 "Hello World!",
如果为 false 就打印错误的信息。helloWord 函数返回的是一个 Promise 对象。
在 Promise 对象当中有两个重要方法————resolve 和 reject。
resolve 方法可以使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作,
在这个例子当中就是 Hello World! 字符串。
reject 方法则是将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作。
then
Promise 对象有三种状态:
1.Fulfilled 可以理解为成功的状态
2.Rejected 可以理解为失败的状态
3.Pending 既不是 Fulfilld 也不是 Rejected 的状态,可以理解为 Promise 对象实例创建时候的初始状态。
helloWorld 的例子中的 then方法就是根据 Promise 对象的状态来确定执行的操作,resolve 时执行第一个
函数(onFulfilled),reject 时执行第二个函数(onRejected)。promise模式在任何时刻都处于以下三种状态之一:未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)。以CommonJS Promise/A 标准为例,promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。then方法会返回另一个promise对象,以便于形成promise管道,这种返回promise对象的方式能够支持开发人员把异步操作串联起来,如then(resolvedHandler, rejectedHandler); 。resolvedHandler 回调函数在promise对象进入完成状态时会触发,并传递结果;rejectedHandler函数会在拒绝状态下调用。
示例代码1:
function printHello (ready) {var promise = new Promise(function (resolve, reject) {if (ready) {resolve("Hello");} else {reject("Good bye");}});return promise;
}function printWorld () {console.log('World');
}function printExclamation () {console.log('!!!');
}printHello(true).then(function(message).then(printWorld).then(printExclamation).catch(function(error){console.log(error);});;
函数先执行printHello,返回一个promise对象,通过then将异步操作串联起来。
执行结果应该是 Hello
World
!!!
示例代码2:
function helloWorld (ready) {return new Promise(function (resolve, reject) {if (ready) {resolve("Hello World!");} else {reject("Good bye!");}});}var _this = this;printHello(true).then(function (message) {var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';return fetch(REQUEST_URL).then((response) => response.json()).then((responseData) => {var movie = responseData.movies[1];console.log('data = ', movie.title);return movie.title;})},function (error) {return(error);}).then(function (message) {return message + ' World';}).then(function (message) {return message + '!!!';}).then(function (message) {console.log(message);console.log('finally');}).catch(function(error){console.log(error);});
上面的代码中有两个promise,第一个promise执行完毕后也就是printHello之后,会执行下一个then,
这个then返回了一个获取数据的promise,后面的then拿到的promise都是指向这个promise对象的。上述例子通过链式调用的方式,按顺序打印出了相应的内容。then 可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个 Promise 对象。另外,在 then onFulfilled 的函数当中的返回值,可以作为后续操作的参数。
catch
catch 方法是 then(onFulfilled, onRejected) 方法当中 onRejected 函数的一个简单的写法,也就是说
可以写成 then(fn).catch(fn),相当于 then(fn).then(null, fn)。使用 catch 的写法比一般的写法更加清晰明确。
新手使用容易犯的错误
1.忘记添加catch()方法
这是一个很常见的错误。很多程序员对他们代码中的promise调用十分自信,觉得代码永远不会抛出一个 error ,
也可能他们只是简单的忘了加 catch() 方法。不幸的是,不加 catch() 方法会让回调函数中抛出的异常被吞噬,
在你的控制台是看不到相应的错误的,这对调试来说是非常痛苦的。
为了避免这种糟糕的情况,我已经养成了在自己的promise调用链最后添加如下代码的习惯:
somePromise().then(function () {return aPromise();}).then(function () {return anotherPromise();}).catch(function(error){console.log(error);});
即使你并不打算在代码中处理异常,在代码中添加 catch() 也是一个谨慎的编程风格的体现。在某种情况下
你原先的假设出错的时候,这会让你的调试工作轻松一些。
2.return的混淆乱用
在then方法内部,我们可以做三件事:
1.return 一个promise对象
2.return一个同步的值或者是 undefined
3.同步的 throw 一个错误
理解这三种情况之后,你就会理解promise了。
1.返回另一个promise对象
在有关promise的相关文章中,这种写法很常见,就像上文提到的构成promise链的一段代码:
getUserByName('nolan').then(function (user) {return fetch(REQUEST_URL).then((response) => response.json()).then((responseData) => {} }).then(function () {});
2.返回一个具体的值或者是 undefined
getUserByName('nolan').then(fcuntion (user) {if (inMemoryCache[user.id]) {return inMemoryCache[user.id]; // returning a value!}return inMemoryCache[user.id];// returning a promise}).then(function (userAccount) {// I got a user account})
如果不调用return语句的话,javaScript里的函数会返回 undefined 。这也就意味着在你想返回一些值的时候,
不显式调用return会产生一些副作用。
出于上述原因,养成了一个个人习惯就是在then方法内部永远显式的调用return或者throw。我也推荐你这样做。
3.抛出一个错误
说到throw,这又体现了promise的功能强大。在用户退出的情况下,我们的代码中会采用抛出异常的方式进行处理:
getUserByName('nolan').then(function (user) {if (user.isLoggedOut()) {throw new Error('user logged out!'); // throwing a error!}if (inMemoryCache[user.id]) {return inMemoryCache[user.id]; // returning a value!}return getUserAccountById(user.id); // returning a promise!}).then(function (userAccount) {// I got a user account!}).catch(function (err) {// Boo, I got an error!});
如果用户已经登出的话, catch() 会收到一个错误,如果有promise对象的状态变为rejected的话,
它还会收到一个错误。
在使用promise的时候抛出异常在开发阶段很有用,它能帮助我们定位代码中的错误。比方说,
在then函数内部调用 JSON.parse() ,如果JSON对象不合法的话,可能会抛出异常,在回调函数中,这个异常会被吞噬,但是在使用promise之后,我们就可以捕获到这个异常了。
作者:梅庆
链接:http://www.jianshu.com/p/174d9892283f
來源:简书
浅谈Promise对象在ReactNative中的使用相关推荐
- java对象头_浅谈java对象结构 对象头 Markword
概述 对象实例由对象头.实例数据组成,其中对象头包括markword和类型指针,如果是数组,还包括数组长度; | 类型 | 32位JVM | 64位JVM| | ------ ---- | ----- ...
- android 存储空间监控,浅谈 Android 内存监控(中)
前言 在上篇 浅谈 Android 内存监控(上) 中,我们聊了 LeakCanary,微信的 Matirx 和美团的 Probe,它们各自有不同的应用场景,例如,在开发测试环境,我们会偏向用 Lea ...
- 美育在计算机教育中应用,浅谈在小学信息技术课堂中有效实施美育.
<浅谈在小学信息技术课堂中有效实施美育.>由会员分享,可在线阅读,更多相关<浅谈在小学信息技术课堂中有效实施美育.(9页珍藏版)>请在人人文库网上搜索. 1.北京市第七届京美杯 ...
- 计算机在英语教学中的应用课题,浅谈信息技术在英语教学中的应用
浅谈信息技术在英语教学中的应用 毕业论文 摘要:随着信息技术的发展, 计算机多媒体技术和网络被广泛地应用在外语教学中, 改变了传统外语教学模式.现代化外语教学提高了外语教学水平, 从而培养高素质的外语 ...
- 计算机在汽车专业中的应用,浅谈计算机技术在汽车行业中的应用.doc
浅谈计算机技术在汽车行业中的应用 摘要:文章围绕计算机技术在汽车性能测试方面的运用.计算机技术在汽车监控方面的运用.计算机技术在汽车检修方面的运用三个方面展开讨论,对计算机技术在汽车行业中的运用模式进 ...
- 计算机技术在现代地球科学中的重要性,浅谈GIS技术在地球科学中的应用.doc
浅谈GIS技术在地球科学中的应用.doc 浅谈GIS技术在地球科学中的应用 中图分类号:P9 文献标识码:A 文章编号:1007-0745(2014)02-0181-01 摘要:地理信息系统是指带各种 ...
- java对象头markword_浅谈java对象结构 对象头 Markword
概述 对象实例由对象头.实例数据组成,其中对象头包括markword和类型指针,如果是数组,还包括数组长度; | 类型 | 32位JVM | 64位JVM| | ------ ---- | ----- ...
- java 对象之间转换_浅谈java对象之间相互转化的多种方式
浅谈java对象之间相互转化的多种方式,对象,属性,参数,赋值,不支持 浅谈java对象之间相互转化的多种方式 易采站长站,站长之家为您整理了浅谈java对象之间相互转化的多种方式的相关内容. 第一种 ...
- [原创]浅谈持续集成在测试中的应用
[原创]浅谈持续集成在测试中的应用 今天抽空理了下思路,来谈谈持续集成在测试中的应用,关于持续集成的介绍,可以参见我之前写的 浅谈我对持续集成的理解. 闲话少说,简单先介绍下,持续集成在测试中应用的范 ...
最新文章
- ADF Jar包循环引用会出问题
- python怎么安装包-Python-如何离线安装软件包?
- debain mariadb10配置root
- An error happened during template parsing (template: class path resource [templates/emp/list.html]
- 安卓APP_ 控件(8)—— AlertDialog
- httpurlconnection 封装_不要再封装各种Util工具类了,看看这个框架
- 美团推出极简版 为用户提供“米面粮油”等生活用品采购服务
- 浙江农林大学有计算机专业,浙江农林大学计算机科学与技术专业在职研究生
- 论文翻译:Real-Time High-Resolution Background Matting
- android音乐播放器flac,五款Android手机FLAC,APE无损音乐播放器
- python几行代码实现微信自动发消息
- [橘汁仙剑网出品]仙剑奇侠传六全剧情视频动画配音版[1080P][720P][H264]
- Using Oracle Database 11g Release 2 Result Cache in an Oracle RAC Environment
- 从“黑五”看亚马逊海外购的变与不变
- 微信小程序●云开发部署攻略
- 定时循环发送TCP消息(例如:控制设备的开关机等场景)—— 定时执行专家
- Android自定义控件系列二:自定义开关按钮(一)
- Mask2Former源码解析
- 写给计算机老师的一封信800,写给老师的一封信800字
- 【WCN685X】DFS认证5600~5650频宽CAC测试失败问题问题及解决方案
热门文章
- opencv 直线检测
- vs2019快捷键设置
- argparse subparsers()
- logging.Formatter 日期格式
- 机器学习算法之决策树
- Cannot find class for bean with name解决
- 九、distinct
- html将字符转成浮点数,stm32用串口接收到数据,怎么把接收到的字符串转换成浮点数?...
- 家用计算机内存最大是多少,电脑支持最大内存是多少?选用多大内存才合理?方法技巧要知道...
- java访问map_java.map使用