promise 封装微信小程序 API

前言

很难理解的是,微信小程序 API 为嘛还在用着回调函数去实现异步模式的 API,众所周知,如果涉及到多个这样的异步操作,就势必会陷入到回调地狱,可读性差,异常无法捕获,所以使用 promise 封装微信小程序的 异步API就相当必要。

至于为嘛使用 promise,现在都8102年了,还提这个还有什么必要吗?话不多说,下面进入小程序异步 API的分析 。

分析

微信小程序文档谈到,微信小程序的API都可以传入函数 success,fail 和 complete 来实现异步回调,来接收接口调用结果。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
x: '' ,
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success: function(res) {
console.log(res.data)
},
fail: function(err) {
console.error(err)
}},
complete: function() {
console.log('complete')
}
})

很明显,是一个回调函数实现的异步模式的 API,那如何实现如下的“promise”化的异步编程呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
x: '' ,
y: ''
},
header: {
'content-type': 'application/json' // 默认值
}
}).then(res => {
console.log(res.data)
}, err => {
console.error(err)
}).finally(() => {
console.log('complete')
})

实现

下面是我的封装实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//需要 promise 封装的 API
const wxApi = [
"getSystemInfo",
"showModal",
"showToast",
"showLoading",
"request",
"getUserInfo",
"openSetting",
"login",
"getSetting",
"reLaunch",
"navigateTo"
];

Promise.prototype.finally = function(callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason =>
P.resolve(callback()).then(() => {
throw reason;
})
);
};
//
wxApi.forEach(key => {
const wxFn = wx[key];
if (
wxFn &&
Object.prototype.toString.call(wxFn).slice(8, -1) === "Function"
) {
Object.defineProperty(wx, key, {
get() {
return (option = {}) => {
if (option.success || option.fail || option.complete)
return wxFn(option);
return new Promise((resolve, reject) => {
wxFn({
...option,
success(res) {
resolve(res);
},
fail(err) {
reject(err);
}
});
});
};
}
});
}
});

这里简单说几句要点:

  1. 本质是用Object.defineProperty实现 getter 取值函数,改写了原生 wx 的 API。
  2. 判断 wx[api]的传参options,做到能使用”promise”化的写法的同时,还兼容团队原来的写法(即用传入函数 success,fail 和 complete)。
  3. 因为微信小程序存在监听事件、同步模式等不适用异步编程的 API,本来是想着循环wx 下所有 API进行改造,因为没有确切异步模式API 函数名的命名规则,所以这里才把需要用到改造的 api放进wxApi的数组。
  4. 为实现complete回调函数,改造小程序Promise,增加Promise.prototype.finally实现