Promise的理解及async/await的基本用法
Promise 是一个构造函数,new Promise 返回一个 promise 对象,接收一个带有 resolve 和 reject 两个参数的函数,这个函数在 Promise 构造函数返回所创建 promise 实例对象前被调用。
var p = new Promise(function(resolve, reject) { resolve() // 成功时调用 reject() // 失败时调用 }); p.then(function(res) { // 从resolve得到正常结果 }, function(res) { // 从reject得到错误信息 })
resolve,reject 是一个函数,处理结束后调用 resolve 或 reject。当调用resolve,会把当前promise对象状态由 pending 标记成功(fulfilled),当调用 reject 会把状态由 pending 标记失败(rejected)。
Promise的三种状态:
-
pending :挂起,当前promise执行的任务,正在执行中
-
fulfilled: 完成,当前promise对象执行的任务,已经完成,并且是成功状态
-
rejected: 完成,当前promise对象执行的任务,已经完成,并且处于失败的状态
封装一个支持Promise API的延时函数:
function timeOut(time){ // 这个函数中就需要返回一个Promise对象 return new Promise((resolve, reject) => { setTimeout(function(){ // resolve和reject在调用的时候,是可以传递数据的,这个数据会最终被传递到成功或者失败的回调函数中 resolve(123) // resolve() // reject() }, time) }) }
基于Promise处理Ajax请求:
function queryData(url) { return new Promise(function(resolve, reject){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if(xhr.readystate !== 4) return; if(xhr.readystate === 4 && xhr.status === 200){ resolve(xhr.responseText); }else{ reject('出错了'); } } xhr.open('get', url); xhr.send(null); }) } queryData('http://localhost:3000/data') .then(function(res){ console.log(res); }, function(err){ console.log(err) }) //发送多次请求 queryData('url1') .then(function(data){ return queryData('url2'); }) .then(function(data){ return queryData('url3'); }) .then(function(data){ console.log(data); })
当 Promise 对象的 fulfilled 或 rejected 任一状态出现时,就会调用 Promise 对象的 .then 方法中绑定的函数。
then 参数中的函数返回值:
-
返回 Promise 实例对象
-
返回的该实例对象会调用下一个 then
-
-
返回普通值
-
在then方法中,可以直接 return 数据而不是Promise对象
-
返回的普通值会直接传递给下一个 then,通过 then 参数中函数的参数接受该值
-
常用API:
-
.then() 得到异步任务的成功信息
promise .then( function() { console.log('成功的回调') }, function() { console.log('失败的回调') } )
-
.catch() 获取异常信息
Promise .then(function() { console.log('成功的回调') }) .catch(function() { consloe.log('失败的回调') })
效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死,而是会进到这个catch方法中。
-
.finally() 成功与否都会执行(还不是正式标准)
-
Promise.all() 并发处理多个异步任务,所有任务都执行完成才执行回调函数
const p1 = new Promise((resolve, reject) => { resolve(1) }) const p2 = new Promise((resolve, reject) => { resolve(2) }) const p3 = new Promise((resolve, reject) => { resolve(3) }) Promise .all([p1, p2, p3]) .then(res => { console.log("所有异步操作完成了", res) //res: 三个结果的数组,结果顺序和promise实例数组顺序是一致的 }) .catch(err => { console.log(err) })
-
Promise.race() 只要有一个任务完成就会执行回调得到结果
Promise .race([p1, p2, p3]) .then(res => { console.log("有一个异步率先完成了", res) })
拓展 async/await 的基本用法
async 和 await 这两个关键字是es7提供的,它们可以将Promise的写法进行简化,async和 await 必然同时出现(有 await 必然会有 async)。
-
async 关键字用于函数上(async 函数的返回值是 Promise 实例对象)
-
await 关键字用于 async 函数中(await 可以得到异步的结果)
async function queryData(id){ const ret = await axios.get('/data'); return ret; } queryData.then(ret => { console.log(ret); })
多个异步请求的场景
async function queryData(id){ const info = await axios.get('/async1'); const ret = await axios.get(`/async2?info=`+info.data); return ret; } queryData.then(ret => { console.log(ret); })
async 和await异常的处理(失败的回调) 使用 try和catch即可
语法:
try { // 成功的回调 } catch(err) { // 失败的回调 }
例:
async deleteUser(id) { // 成功的回调 try { await this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }) let res = await this.$http({ url: `users/${id}`, method: "delete", data: id }) console.log(res) if (res.data.meta.status === 200) { console.log('success', res) } } // 失败的回调 catch (err) { console.log('已取消删除') } }