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

来源:互联网 发布:linux编程手册 pdf 编辑:程序博客网 时间:2024/05/16 18:37

为什么使用Promise

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

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

样例一 :

// 显示”载入中”,在一秒后消失wx.showLoading({    title: "载入中",    success: function () {        setTimeout(function () {            wx.hideLoading()        }, 1000)    },    fail: function(){},    complete: function(){}});

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

样例二 :

// 显示“保存中”,一秒后隐藏,半秒后显示“载入中”,一秒后隐藏wx.showLoading({    title: "保存中",    success: function () {        setTimeout(function () {            wx.hideLoading({                success: function () {                    setTimeout(function () {                        wx.showLoading({                            title: "载入中",                            success: function () {                                setTimeout(function () {                                    wx.hideLoading()                                },1000)                            }                        })                    }, 500)                }            })        }, 1000)    }})

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

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

样例三 :

wsAPI.taskSequence()    .then(() => wsAPI.showLoading({title: "保存中"}))    .then(() => wsAPI.sleep(1000))    .then(() => wsAPI.hideLoading())    .then(() => wsAPI.sleep(500))    .then(() => wsAPI.showLoading({title: "载入中"}))    .then(() => wsAPI.sleep(1000))    .then(() => wsAPI.hideLoading())    .then(() => console.log("done"))

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

比如 () => 5 就会 return 5

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

封装实现

wsAPI的源代码实现如下:

let nullFn = () => {};function IllegalAPIException(name) {    this.message = "No Such API [" + name + "]";    this.name = 'IllegalAPIException';}let services = {    sleep: (time) => {        return new Promise(function (resolve, reject) {            setTimeout(resolve, time);        })    },    stop: () => {        return new Promise(function (resolve, reject) {        })    },    taskSequence: () => {        return new Promise(function (resolve, reject) {            resolve()        })    }};export let wsAPI = new Proxy(services, {    get: function (target, property) {        if (property in target) {            return target[property];        } else if (property in wx) {            return (obj) => {                return new Promise(function (resolve, reject) {                    obj = obj || {};                    obj.success = (...args) => {                        resolve(...args)                    };                    obj.fail = (...args) => {                        reject(...args);                    };                    obj.complete = nullFn;                    wx[property](obj);                });            }        } else {            throw new IllegalAPIException(property);        }    }});

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

样例四 :

// taskSequencewsAPI.taskSequence()    .then(() => wsAPI.showLoading({title: "保存中"}))    .then(() => wsAPI.sleep(1000))    .then(() => wsAPI.hideLoading())    .then(() => wsAPI.sleep(500))    .then(() => wsAPI.showLoading({title: "载入中"}))    .then(() => wsAPI.sleep(1000))    .then(() => wsAPI.hideLoading())    .then(() => console.log("done"))// 没有 taskSequence,第一个promise就和下面的不对齐wsAPI.showLoading({title: "保存中"})    .then(() => wsAPI.sleep(1000))    .then(() => wsAPI.hideLoading())    .then(() => wsAPI.sleep(500))    .then(() => wsAPI.showLoading({title: "载入中"}))    .then(() => wsAPI.sleep(1000))    .then(() => wsAPI.hideLoading())    .then(() => console.log("done"))

样例五 :

wsAPI.taskSequence()    .then(() => wsAPI.showModal({title: "保存", content: "确定保存?"}))    .then(res => {        if (!res.confirm) {            return wsAPI.stop();        }    })    .then(() => console.log("to save"))    .then(() => wsAPI.showLoading({title: "保存中"}))    .then(() => wsAPI.sleep(1000))    .then(() => wsAPI.hideLoading())    .then(() => console.log("done"))
原创粉丝点击