零、回顾
在上节课我们主要是基于 Promise 加 await、async关键字改写了登录模块代码,
但是我们在自动登录这一块的代码仍然有问题,这节课我们看一下,
如何在接口调用中实现微信用户的自动登录。
一、上节课的代码遇到的两个问题
1.代码只要在页面中定义,就会被隐含执行。
2.关于 Promise 的catch
1.1 代码只要在页面中定义,就会被隐含执行。
我们在一个page界面中,给Promise类对象扩展了一个any方法。
这个any方法用于实现js中尚处于草案阶段一个Promise.any的设计,
但是这个方法只要被放在任何一个page页面的顶部,即使这个page没有在app.json里面的
pages字段里面声明,这段代码也会被默默的去执行掉,
这一点在上节课的代码演示中已经验证过了。
但是如果我们把Promise.any的扩展代码,放在一个非page文件中,例如lib目录下的any.js这个文件里面,
只要这个文件不被显式地引用,这个代码它就不会被初始化。
为什么为这样呢?可能小程序在启动的时候,预先扫描了所有的page页面,
即使这个页面它没有被显式引用,也会被扫描,
它扫描的时候,所有这个文件作用于下面的代码,都会被隐默执行。
为了避免这种在犄角旮旯里有悄悄执行的代码,
我们最好将这段Promise.any这样的代码,放在一个独立的文件里面,然后显式地在app.json中去显式的引用。
我们看一下上面的代码,我们在独立的文件里面去定义这个方法的一个代码,
下面的代码我们在app.js中,通过import引入上面独立的代码模块。
这样可以使我们代码更加的清晰,也便于我们理解和维护。
1.2 关于 Promise 的catch
我们先看一下关于Promise的catch的机制是怎样的?
我们在定义它的子实例的时候,每一个都添加了一个catch,
也就是prommise1、promise2、promise3,它们后面每一个都有一个catch。
在Promise.any中,针对每一个Promise的子实例,还添加了一个reject回调函数。
这个时候我们执行代码,它输出是这样的。
这个它代表Promise它是成功输出了,这个输出结果,与我们预期是不符合的。
正常情况下一个子实例发生错误,不应该走到总实例接受状态的分支。
那么这是为什么呢?原因在于Promise它不是一个观察者对象。
它并不像这个事件一样,它可以冒泡派发事件。
对于Promise的每一个拒绝状态或者接受状态的环节,如果不向下传递,
那在下一个环节里面是获知不到它的一个状态的。
在上面的代码中,我们直接在promise1上面添加了一个状态,它进行了一个简单的打印操作,
但是并没有进一步把这个错误抛出来,并没有向下去传递,这个就相当于把这个状态处理完了,
然后告诉外层这个promise它已经有一个处理结果了,所以呢我们在总实例上,才捕获到一个空的结果对象。
就是我们看到的这样一个 res undefined,这样一个打印结果。
要想改写这个实例,我们只需要在处理错误的地方,将错误向下传递就可以了。
例如改造之后的代码我们看一下。
在最外层的子实例promise1上面,我们将错误打印,再讲=将错误使用throw关键字给抛出来,
这样在Promise.any内部仍然可以出发reject回调的执行。
如果没有throw err的话,走不到reject(err)里面。
在上面的代码中,我们先执行的是上面的catch,然后才会走到下面的reject分支里面去。
我们可以将Promise这个处理错误的机制与Koa框架里面的洋葱式中间件的设计做对比。
在上面的代码中,无论是使用throw抛出错误,还是基于reject传递错误,都相当于Koa框架里面的next。
这就是上节课我们在代码演示的时候,遇到的两个问题,这两个问题都值得我们注意一下。
二、如何在接口请求中,整合用户的自动登录
2.1 wxp 模块化
app.js
import wxp from "./lib/wxp.js"
App({
wxp: wxp,
lib/wxp.js
import { promisifyAll } from 'miniprogram-api-promise';
const wxp = {}
promisifyAll(wx, wxp)
wxp.request2 = function (args) {
let token = wx.getStorageSync('token');
if (token) {
if (!args.header) args.header = {}
args.header["Authorization"] = `Bearer ${token}`
}
return wxp.request(args).catch(err => console.log("err", err))
}
export default wxp;
index.wxml
<view class="page-section">
<text class="page-section__title">3.6 模块化</text>
<view class="btn-area">
<button bindtap="requestOneHomeApi" type="primary">请求user/home接口</button>
</view>
</view>
index.js
// 3.6 模块化
async requestOneHomeApi(e) {
let res3 = await getApp().wxp.request2({
url: "http://localhost:3000/user/home",
});
if (res3) console.log("res3", res3);
},
token信息
清除本地token
请求里面没有带token信息
三、总结
这节课主要梳理了两个问题,一个是代码在page页面中,可能会被隐藏执行,虽然这个页面没有被用到。
另外一个问题是关于Promise对象的catch处理,它像Koa框架里面的洋葱中间件机制一样,
在使用时需要我们注意一下向下传递。
下节课我们在request2方法的基础之上,实现一个request3这样一个方法,
这个方法将用于实现用户自动登录的整合。