零、回顾
在上节课我们主要介绍了观察者模式,
并据此模式实现了一个event模块,
这节课我们基础用户登录的自动整合,
尝试在wxp模块当中扩展出一个request3这样的一个接口。
一、在wxp组件中扩展实现request3接口
3.7中,
当我们单击手动开启登录的时候,
它底部有一个面板滑出。
接下来我们要实现的功能是,
如果是我们用request3去调用接口的时候,
如果发现用户没有登录,也就是没有token,
那么我们把面板自动给它呼出来,让它滑出,
滑出以后,然后用户点击按钮去登录,
登录完成以后,自动地让面板消失,
然后继续我们刚才已经停止的接口请求。
这个大概就是我们想要实现的一个功能
ilb/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))
}
wxp.request3 = function (args) {
let token = wx.getStorageSync('token');
if (!token) {
return new Promise((resolve, reject) => {
let pageStack = getCurrentPages();
if (pageStack && pageStack.length > 0) {
let currentPage = pageStack[pageStack.length - 1];
currentPage.setData({
showLoginPanel: true
})
getApp().globalEvent.once("loginSuccess", () => {
wxp.request2(args).then(res => {
resolve(res)
}, err => {
console.log("err", err)
reject(err)
})
})
} else {
reject("page valid err")
}
})
}
return wxp.request2(args)
}
export default wxp;
pages/api/index.wxml
<view class="page-section">
<text class="page-section__title">3.9 request3</text>
<view class="btn-area">
<button bindtap="testRequest3" type="primary">request3</button>
</view>
</view>
pages/api/index.js
Page({
data: {
showLoginPanel:false
},
async testRequest3(e){
const app = getApp();
let res3 = await app.wxp.request2({
url:'http://localhost:3000/user/home'
})
if(res3) console.log("res3",res3);
let res4 = await app.wxp.request3({
url:'http://localhost:3000/user/home'
})
if(res4) console.log("res4",res4);
},
......
})
二、开发中遇到的问题
2.1 wx.request 经 Promise 封装后,如何拿到 RequestTask 实例
实现一:
创建新的类,Request这个类,封装了wx.request接口。 但是这种方法要改变旧的开发模式,会带来新的开发负担。
class Request {
constructor(parms) {
...
this.requestTask = null;
}
request(method, url, data) {
const vm = this;
return new Promise((resolve, reject) => {
this.requestTask = wx.request({
...
success(res) {
resolve(res);
},
fail() {
reject({...});
}
});
});
}
abort() {
if (this.requestTask) {
this.requestTask.abort();
}
}
}
module.exports = Request;
实现二:
是把原生接口返回的RequestTask的实例, 挂载到我们返回的Promise实例上面, 但是这种方式,它会对原生的代码有侵入, 并且在我们代码里面,Promise实例并不是保持不变的, 在wxp.request3中,Promise实例就有所改变。
实现三:
这两种方式虽然可以达到同样的目的, 但却不是我们要采用的最终的一个方法, 那么更好的方式是利用javascript对象被引用传递的这样一个特点, 在这个参数上做手脚。
miniprogram/node_modules/miniprogram-api-promise/src/promise.js:
function _promisify(func) {
if (typeof func !== 'function') return fn
return (args = {}) =>{
return new Promise((resolve, reject)=> {
let rtnObj = func(
Object.assign(args, {
success: resolve,
fail: reject
})
)
if (args.onReturnObject) args.onReturnObject(rtnObj)
})
}
}
我们看一下这个代码,
我们只需要在这个模块当中加一个固定的一个回调属性,
就可以解决这个问题了
if (args.onReturnObject) args.onReturnObject(rtnObj)
function _promisify(func) {
if (typeof func !== 'function') return fn
return (args = {}) =>
new Promise((resolve, reject) => {
let rtnObj = func(
Object.assign(args, {
success: resolve,
fail: reject
})
)
if (args.onReturnObject) args.onReturnObject(rtnObj)
})
}
工具–npm构建
<button bindtap="requestHomeApiByReq4" type="primary">test abort</button>
requestHomeApiByReq4(e){
getApp().wxp.request4({
url:'http://localhost:3000/user/home',
onReturnObject(rtn){
rtn.abort();
}
}).catch(err=>{
console.log(err)
})
},
重点:
三、总结
这节课我们主要扩展了wxp模块的request3这个方法,
下节课开始学习tabbar组件。
|