微信小程序的大部分api是异步的。javascript
简单地举个🌰: wx.showToast(Object object)html
wx.showToast({
title: '成功',
icon: 'success',
duration: 2000,
success: function(res) { // TODO },
fail: function(err) { // TODO }
});
复制代码
事实上这样的api 写的真够好,可是对于使用者来讲并不友好。因此,为了方便同事们更加舒爽地去写代码,因而我开始琢磨封装一个小程序api的promisefy的函数。java
那么到底怎么封装呢?webpack
// defaultProps为默认属性,extraProps为定制化的属性
/** * promisefy 微信内置函数 * @param fn * @return { promise } */
const promisefy = fn => defaultProps => extraProps => new Promise((resolve, reject) => fn({
...defaultProps,
...extraProps,
success: res => resolve(res),
fail: err => reject(err),
}));
复制代码
那么到底怎么使用呢?web
const showToast = promisefy(wx.showToast)({
title: '',
icon: "none",
duration: 2000,
confirmColor: '#ff673f',
mask: true
});
showToast({ title: 'title' }); // 便可使用
复制代码
那么这个promisefy还能怎么用呢? 1.咱们可能会常常使用storage相关的api, 那么究竟是把对象JSON.stringify, 再setStorage。须要使用的时候再getStorage, 最后JSON.parse呢?固然这是一种解决方案。若是使用promisefy,能够这样干。npm
/** * * @param 须要往LocalStorage里面存数据 * @returns {Promise<any[] | never>} */
const setStorage = (param = {}) => {
if (!Object.keys(param).length) throw new Error('输入的对象不为空');
return Promise.all(Object.entries(param)
.map(item => promisefy(wx.setStorage)({
key: item[0],
data: item[1]
})()));
};
setStorage({ a:1, b:2 });
复制代码
/** * * @param 须要从storage 读取的key。 * 单个值直接传string, 多个值传数组 * eg. ['key1', 'key2', 'key3'] 或者 'key1' ; * @returns {key1: value1, key2: value2, key3: key3 } */
const getStorage = param => Promise.all(
Object.entries(((typeof param) === 'string') ? [param] : param)
.map(item => promisefy(wx.getStorage)({ key: item[1] })()
.then(res => ({ [`${item[1]}`]: res.data }))))
.then(res => res.reduce((prev, curr) => ({ ...prev, ...curr }), {}));
getStorage('a'); // { a: 1 },
getStorage(['a', 'b']); // { a: 1, b: 2 },
复制代码
/** * @param 须要从storage 清除记录eg. [key1, key2], key3。 */
const removeStorage = param => Promise.all(
Object.entries(((typeof param) === 'string') ? [param] : param)
.map(item => promisefy(wx.removeStorage)({ key: item[1] })()));
removeStorage('a');
removeStorage(['a', 'b']);
复制代码
2.对于有router 的页面咱们常常会出现router 的三种跳转方案。例如微信就提供了三种api:navigateTo,redirectTo,navigateBack,这里没有包含小程序跳小程序的api。那么咱们是否是能够封装一个公共的方法呢?小程序
// 路径参数的拼接
const obj2Url = params => {
if (params instanceof Array || typeof params === 'number') throw new Error('跳转参数限制于string和对象');
// 若是路径参数为 object, 作如下转换
if (typeof params === 'object') {
const rawParams = Object.entries(params).reduce((acc, cur) => {
if ((!cur[1]) && ((typeof cur[1]) !== 'boolean')) console.warn(`${cur[0]}的值为空, 请检查缘由!`);
return `${acc + cur[0]}=${cur[1]}&`;
}, '');
params = rawParams.substr(0, rawParams.length - 1);
}
return params;
};
/** * * @param page 须要跳转的页面或者页面路径(若是是"pages/a/b/b"这样的路径,page='pages/a/b/b', specialUrl=true ) * @param type * @param params * @param specialUrl * @return {*} */
const jumpTo = (page = 'index', type = 'navigate', params = '', specialUrl = false) => {
const { navigateTo, redirectTo, navigateBack } = wx;
const types = {
navigate: url => promisefy(navigateTo)({ url })(),
redirect: url => promisefy(redirectTo)({ url })(),
back: delta => promisefy(navigateBack)({ delta })(),
};
params = obj2Url(params);
console.log('**test**', 'params', params, `${page}?${params}`);
if (specialUrl) return types[type](params ? `${page}?${params}` : page);
// 获取跳转参数,若是为数字,则为navigateBack,反之为 navigateTo 或 navigateBack。
const jumpPram = (typeof page === 'number') ? page : `/pages/${page}/${page}${params ? `?${params}` : ''}`;
console.log(`%c**跳转参数**jumpPram** ${jumpPram}`, 'color:white;background:green');
sendTrack(`**跳转参数**jumpParam** ${jumpPram}`);
return types[type](jumpPram);
};
jumpTo('a'); // navigateTo到a页面
jumpTo('a', 'navigate', { m: 'm' }); // navigateTo到a页面 ,路径参数为?m=m
jumpTo('a', 'redirect', { m: 'm' }); // redirectTo到a页面 ,路径参数为?m=m
jumpTo(1, 'redirect', { m: 'm' }); // back 上一步 ,路径参数为?m=m
复制代码
1.native 小程序开发者。(下载babel-polyfill,导入regeneratorRuntime)微信小程序
import regeneratorRuntime from '你放置的文件夹';
const showLoading = promisefy(wx.showLoading)({ title: '加载中', mask: true });
const hideLoading = () => wx.hideLoading();
const showToast = promisefy(wx.showToast)({ title: 'title', content: '', mask: true });
const Loading = { show: showLoading, hide: hideLoading };
const Toast = { show: showToast };
const handleErr = (e, cb) => {
Loading.hide();
if ((typeof e) === 'string') {
Toast.show({ title: e || '服务器异常,请稍后再试' });
} else {
const { message } = e;
Toast.show({ title: message || '服务器异常,请稍后再试' });
}
cb && cb();
};
const fetchData = () => {}
aync function() {
try {
await Loading.show();
const { data } = await fetchData();
this.setData({
data
})
Loading.hide();
} catch (e) {
handleErr(e)
}
}
复制代码
2.webpack和taro 用户直接引入用配置bable 相关npm便可, 可参考api
函数的科里化干了什么?数组
参考 科里化
怎么避免过多使用switch...case,if...else等?
参考 策略模式
扁平化数组操做。
参考 编写扁平化的代码
异常的处理。