1.前言
总结前后端交互的几种方式的时候,突然想起来之前小程序用promise封装ajax,简要记录如下
这几天闲来无事又梳理了下
promise
2.常规封装
function getApi(url, data, successCB) { wx.showLoading({ title: '加载中', }) wx.request({ url: baseUrl + url, data, header: { 'content-type': 'application/json' // 默认值 }, success: (res) => { if (res.code = 200) { // 回调到组件 ,数据给他 successCB && successCB(res.data) } else { wx.showToast({ title: '服务器错误', icon: 'error', duration: 2000 }) } }, fail: (err) => { wx.showToast({ title: '服务器错误', icon: 'error', duration: 2000 }) console.log("错误信息:", err); }, complete(res) { // console.log("complete",res); wx.hideLoading() // wx.stopPullDownRefresh() } }) }
3.promise封装
const getApi = (url, data) => { wx.showLoading({ title: '加载中', mask: true }) // Promise 承诺:处理异步回调 同意 拒绝 return new Promise(function (resolve, reject) { // 只能走一个 要么同意 要么拒绝 // resolve() 回调then() // reject() 回调catch() wx.request({ url: baseUrl + url, data, header: { 'content-type': 'application/json' // 默认值 }, success: (res) => { resolve(res.data) }, fail: () => { wx.showToast({ title: '服务器错误', icon: 'error', duration: 2000 }) reject("服务器错误,请稍后重试"); }, complete(res) { // console.log("complete",res); wx.hideLoading() // wx.stopPullDownRefresh() } }) }) }
4. 调用
var api = require('../../utils/api'); var shopUrl = "" var data = {} api.getApi(shopUrl,data).then(()=>{ //处理数据 }).catch(()=>{ //异常处理 wx.showToast({ title: '服务器错误', icon: 'error', duration: 2000 }) })
5. why 为什么需要 promise
诞生背景,解决了哪些问题
- js中代码都是单线程 异步执行的.实现异步的方式主要是 回调函数
2
.Promise
是异步编程的一种解决方案,比传统的解决方案更合理和更强大。它由社区最早提出和实现,ES6
将其写进了语言标准,统一了用法,原生提供了Promise
对象
6. 基础概念
简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,
Promise
是一个对象,从它可以获取异步操作的消息。Promise
提供统一的 API,各种异步操作都可以用同样的方法进行处可以理解为 君子一诺千金,答应的事情,等我这边忙完,一定会给你个答复,不管拒绝还是同意.
7. 核心要点
1.对象的状态不受外界影响。
Promise
对象代表一个异步操作,有三种状态:pending(进行中)
、fulfilled(已成功)
和rejected(已失败)
。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来它的英语意思就是
“承诺”
,表示其他手段无法改变。
2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise
对象的状态改变,只有两种可能:从
pending
变为fulfilled
和从
pending
变为rejected
。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为
resolved(已定型
)。如果改变已经发生了,你再对Promise
对象添加回调函数,也会立即得到这个结果。这与
事件(Event)
完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的
8. 缺点
1.无法取消
Promise
,一旦新建它就会立即执行,无法中途取消。2.如果不设置回调函数,
Promise
内部抛出的错误,不会反应到外部。3.当处于
pending
状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
9. 案例
随机数大于4 你赢了 武林盟主
比多久不清楚,所有用定期模拟,间隔时间也是变量
var test = (resolve, reject) => { var randomNum = Math.random() * 10 console.log("随机是:", randomNum); // 比武什么时候结束 是不确定 ,用定时器模拟这个不确定 setTimeout(() => { if (randomNum > 4) { resolve("周润发 赌王 赢了") } else { reject("周润发 问鼎赌王 失败") } }, 1000 * randomNum) }
外界并不关心你们这场 比武的过程,只关注结果
10. then 你赢的结果
函数执行成功 告诉
Promise
对象:执行then
then
方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例
)。因此可以采用链式写法,即
then
方法后面再调用另一个then
方法。
var p1 = new Promise(test) var p2 = p1.then(res => { console.log("成功:", res); })
Promise
实例具有then
方法,也就是说,then
方法是定义在原型对象Promise.prototype
上的。它的作用是为
Promise
实例添加状态改变时的回调函数
。前面说过,then方
法的第一个参数是resolved
状态的回调函数,第二个参数是rejected
状态的回调函数,它们都是可选的。
11. catch 你输的结果
函数执行
失败
时,我们告诉Promise
对象: 执行catch
方法
var p3 = p2.catch(err=>{ console.log("失败:",err) })
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数
12. finally 不管输赢 都会走
finally()
方法用于指定不管Promise
对象最后状态如何,都会执行
的操作。该方法是 ES2018 引入标准的。
var p4 = p3.finally(()=>{ console.log("都会执行") })
13. 链式写法
new Promise((resolve, reject) => { var randomNum = Math.random() * 10 console.log("随机是:", randomNum); // 比武什么时候结束 是不确定 ,用定时器模拟这个不确定 setTimeout(() => { if (randomNum > 4) { resolve("周润发 赌王 赢了") } else { reject("周润发 问鼎赌王 失败") } }, 1000 * randomNum) }).then(res=>{ console.log("成功:",res); }).catch(err=>{ console.log("失败:",err); })
14.原生ajax封装
这里只是简单的例子 ,具体的 请求参数 还需要另做
<button onclick="sendBtn()">发送</button> <script> function sendBtn() { ajax("GET", "./data.json").then(res => { console.log("res:", res) }).catch(err => console.log(err)) } // ajax函数将返回Promise对象: function ajax(method, url, data) { var request = new XMLHttpRequest(); return new Promise(function (resolve, reject) { request.onreadystatechange = function () { if (request.readyState === 4) { if (request.status === 200) { resolve(JSON.parse(request.responseText)) } else { reject(request.status); } } }; request.open(method, url); request.send(data); }); } </script>
15. 总结
Promise最大的好处是:
1.在异步执行的流程中, 把执行代码和处理结果的代码清晰地分离了
- 将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
3.Promise对象提供统一的接口,使得控制异步操作更加容易