微信小程序实践——用Promise 封装API

为什么使用Promise

如果新接触 Promise 的话,在网上能找到很多介绍 Promise 及其使用的文章(比如:ECMAScript 6 入门 / Promise 对象),这里就不赘述了,简而言之就是用来处理异步调用的一大利器。

微信小程序的API都可以传入函数 success,fail 和 complete 来实现异步回调。

样例一 :


 
 
  1. // 显示”载入中”,在一秒后消失
  2. wx.showLoading({
  3. title: "载入中",
  4. success: function () {
  5. setTimeout( function () {
  6. wx.hideLoading()
  7. }, 1000)
  8. },
  9. fail: function(){},
  10. complete: function(){}
  11. });

原生的 success,fail 和 complete 已能够满足基本的异步回调了,但是如果遇到多个连续的阻塞任务,会造成多层嵌套(如样例二所示),就很奔溃。

样例二 :


 
 
  1. // 显示“保存中”,一秒后隐藏,半秒后显示“载入中”,一秒后隐藏
  2. wx.showLoading({
  3. title: "保存中",
  4. success: function () {
  5. setTimeout( function () {
  6. wx.hideLoading({
  7. success: function () {
  8. setTimeout( function () {
  9. wx.showLoading({
  10. title: "载入中",
  11. success: function () {
  12. setTimeout( function () {
  13. wx.hideLoading()
  14. }, 1000)
  15. }
  16. })
  17. }, 500)
  18. }
  19. })
  20. }, 1000)
  21. }
  22. })

上面的例子有七个阻塞任务:显示“保存中”,停顿一秒,隐藏,停顿半秒,显示“载入中”,停顿一秒,隐藏。从直觉上来思考,这些任务应该是以队列的形式存在,一个完成了再开始下一个,而非层层嵌套,这也是使用Promise的一大原因,可以链式调用。

上面的例子如果用Promise封装之后的API来写,看起来就非常直观(样例三)

样例三 :


 
 
  1. wsAPI .taskSequence()
  2. .then( () => wsAPI.showLoading({ title: "保存中"}))
  3. .then( () => wsAPI.sleep( 1000))
  4. .then( () => wsAPI.hideLoading())
  5. .then( () => wsAPI.sleep( 500))
  6. .then( () => wsAPI.showLoading({ title: "载入中"}))
  7. .then( () => wsAPI.sleep( 1000))
  8. .then( () => wsAPI.hideLoading())
  9. .then( () => console.log( "done"))

注: (A)=>{B} 是 ES6 的箭头函数,相当于 function(A){B},箭头函数不用显式 return。

比如 () => 5 就会 return 5


 
 
  1. console.log((() => 5)()) // 5

封装实现

wsAPI的源代码实现如下:


 
 
  1. let nullFn = () => {
  2. };
  3. function IllegalAPIException(name) {
  4. this.message = "No Such API [" + name + "]";
  5. this.name = 'IllegalAPIException';
  6. }
  7. let services = {
  8. sleep: (time) => {
  9. return new Promise(function (resolve, reject) {
  10. setTimeout(resolve, time);
  11. })
  12. },
  13. stop: () => {
  14. return new Promise(function (resolve, reject) {
  15. })
  16. },
  17. taskSequence: () => {
  18. return new Promise(function (resolve, reject) {
  19. resolve()
  20. })
  21. }
  22. };
  23. export let wsAPI = new Proxy(services, {
  24. get: function (target, property) {
  25. if (property in target) {
  26. return target[property];
  27. } else if (property in wx) {
  28. return (obj) => {
  29. return new Promise(function (resolve, reject) {
  30. obj = obj || {};
  31. obj.success = (...args) => {
  32. resolve(...args)
  33. };
  34. obj.fail = (...args) => {
  35. reject(...args);
  36. };
  37. obj.complete = nullFn;
  38. wx[property](obj);
  39. });
  40. }
  41. } else {
  42. throw new IllegalAPIException(property);
  43. }
  44. }
  45. });

wsAPI 用 Proxy(ECMAScript 6 入门 / Proxy)重新封装了 wx 的所有API。并新增了 sleep ,stop 和 taskSequence。sleep 用于阻塞一段时间;taskSequence 是一个空的 Promise,让代码看起来更整齐美观,可读性更好(样例四);stop 用于停止任务序列进行下去(样例五)

样例四 :


 
 
  1. // taskSequence
  2. wsAPI .taskSequence()
  3. .then( () => wsAPI.showLoading({ title: "保存中"}))
  4. .then( () => wsAPI.sleep( 1000))
  5. .then( () => wsAPI.hideLoading())
  6. .then( () => wsAPI.sleep( 500))
  7. .then( () => wsAPI.showLoading({ title: "载入中"}))
  8. .then( () => wsAPI.sleep( 1000))
  9. .then( () => wsAPI.hideLoading())
  10. .then( () => console.log( "done"))
  11. // 没有 taskSequence,第一个promise就和下面的不对齐
  12. wsAPI .showLoading({ title: "保存中"})
  13. .then( () => wsAPI.sleep( 1000))
  14. .then( () => wsAPI.hideLoading())
  15. .then( () => wsAPI.sleep( 500))
  16. .then( () => wsAPI.showLoading({ title: "载入中"}))
  17. .then( () => wsAPI.sleep( 1000))
  18. .then( () => wsAPI.hideLoading())
  19. .then( () => console.log( "done"))

样例五 :


 
 
  1. wsAPI .taskSequence()
  2. .then( () => wsAPI.showModal({ title: "保存", content: "确定保存?"}))
  3. .then( res => {
  4. if (!res.confirm) {
  5. return wsAPI .stop();
  6. }
  7. })
  8. .then( () => console.log( "to save"))
  9. .then( () => wsAPI.showLoading({ title: "保存中"}))
  10. .then( () => wsAPI.sleep( 1000))
  11. .then( () => wsAPI.hideLoading())
  12. .then( () => console.log( "done"))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值