Promise和async/await
1、promise对象promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。 const promise = new Promise(function(resolve,reject) { if (){ resolve(value); } else { reject(error); } }); promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject,它们是两个函数,由 JavaScript 引擎提供,不用自己部署。 resolve 函数将 promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved)可以将数据作为参数传递出去。reject 函数的作用是,将 promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),也可以将某些错误信息作为参数传递出去。 由于Promise 新建后会立即执行,所以可以在 promise 外面再包裹一层函数: function timeout(ms) { return new Promise((resolve,reject) => { setTimeout(resolve,ms,‘done‘); }); } timeout(100).then((value) => { console.log(value); }); ? 1.1、then() 方法Promise 实例是一个对象,不是一个函数。promise?实例生成以后,可以用 then 方法分别指定 resolved?状态和 rejected?状态的回调函数。 let promise = new Promise(function(resolve,reject) { if (){ resolve(value); } else { reject(error); } }); promise.then(function(value) { console.log(value) },function(error) { console.log(error) }); then 方法可以接受两个回调函数作为参数。第一个回调函数是 promise 对象的状态变为 resolved 时调用,第二个回调函数是 promise 对象的状态变为 rejected 时调用,第二个函数是可选的,不一定要提供。这两个函数都接受 promise 对象传出的值作为参数。 ? 1.2、then() 方法的链式写法then?方法返回的是一个新的 promise?实例,因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。 1.2.1、then 方法里面返回一个确定值时在一个 then() 方法里面你可以 return 一个确定的“值”,此时?then 会将这个确切的值传入一个默认的新的 Promise 实例,并且这个 Promise 实例会立即置为 fulfilled 状态,将 return 的值作为 resolve 方法的参数传递出去,以供接下来的 then 方法里使用。 let p1 = new Promise((resolve,reject) => { resolve(‘aaa‘) }) p1.then((data) => { data = data + ‘bbb‘ return data // 此时data会作为resolve的参数传递出去 }).then((val) => { console.log(val + ‘ sucess‘); },(err) => { console.log(err + ‘ error‘); }) //输出: aaabbb sucess ? 1.2.1、then 方法里面返回一个 promise 实例如果 then 方法里面返回的还是一个 promise 对象,这时后一个回调函数,就会等待该 promise 对象的状态发生变化,才会被调用。 //第一个异步任务 function a(){ return new Promise(function(resolve,reject){ resolve("a函数"); }); } //第二个异步任务 function b(data_a){ return new Promise(function(resolve,reject){ console.log(data_a); resolve("b函数"); }); } //连续调用 a().then(function(data){ return b(data); // 此时then方法里面返回的是一个promise对象,后面的then会等待该promise对象的状态发生改变才会被调用 }).then((data) => { console.log(data + ‘sucess‘) },(err) => { console.log(err + ‘rejected‘) }) //输出:a函数 b函数sucess 上面的最后一个 then 函数等待前面的 then 函数里面的 promise 对象状态发生改变,如果变为 resolved?,就调用第一个回调函数,如果状态变为 rejected,就调用第二个回调函数。 1.2.1、then 方法里面不返回如果 then 方法不返回数据,那么后面的 then 将无法获取到前面的数据,但是后面的 then 方法仍能执行。 //第一个异步任务 function a(){ return new Promise(function(resolve,reject){ console.log(data_a); resolve("b函数"); }); } a().then(function(data){ console.log(data) //不返回 }).then((data) => { console.log(data + ‘ sucess‘) },(err) => { console.log(err + ‘ rejected‘) }) //输出: a函数 undefined sucess ? 1.3、catch() 方法
p.then((val) => console.log(val)) .then(null,(err) => console.log(err)); // 相当于 p.then((val) => console.log(val)) .catch((err) => console.log(err)); catch 方法中断调用链: 在很多情况下,如果连续的几个异步任务,其中某个异步任务处理失败,那么接下来的几个任务很大程度上就不需要继续处理了,我们可以使用 catch 方法来终止then的调用链。 function a() { return new Promise(function (resolve,reject) { setTimeout(function () { reject("error"); },1000); }); } //这样做不会中断 //下面输出:222 333 a().then(function (data) { console.log(111); return data },function (data) { //如果是这样处理rejected状态,并不会中断调用链 console.log(222); return data; }).then(function (data) { console.log(333); }) //在调用链的末尾加上catch方法,当某个环节的Promise的异步处理出错时,将中断其后的调用,直接跳到最后的catch //下面直接输出: ‘error‘ a().then(function (data) { console.log(111); return data }).then(function (data) { console.log(222); }).catch(function (e) { //rejected的状态将直接跳到catch里,剩下的调用不会再继续 console.log(e); }); 使用 catch 方法时,如果前面的函数里面有 reject 或者函数里面有错误的话,就会被 catch 方法捕获,立即跳转到 catch 方法里执行。前面的回调函数中,不管是运行中有错误,或者是执行了 reject ,都会立即被? ? 2、async/await 方法async 方法里面有 await 命令,await 命令后面跟着异步操作(可以是请求接口或者其他异步操作等),这时 async 函数会停下来,等待 await 命令后面的异步操作执行完毕,将结果返回,然后再继续执行下去。如果后面再遇到 await 命令仍是如此,所以,async 函数里面可以看做是同步操作,语句都是一行一行地依次执行的,语句执行顺序非常清晰。 2.1、async 函数的定义形式// 函数声明 async function foo() {} const foo = async function () {}; // 对象的方法 let obj = { async foo() {} }; // 箭头函数 const foo = async () => {}; // Class 的方法 class Storage { constructor() { this.cachePromise = caches.open(‘avatars‘); } async getAvatar(name) { const cache = await this.cachePromise; return cache.match(`/avatars/${name}.jpg`); } } 2.2、async 函数里面的 await 命令2.2.1、await 跟着 promise 对象一般来说, function timeout() { return new Promise((resolve) => { setTimeout(function (){ resolve(‘aaa‘) },1000); }); } async function asyncPrint() { let data = await timeout(); console.log(111); console.log(data); } asyncPrint(); //按顺序执行,1秒后依次输出 111 aaa ? 如果是 reject 方法,则 reject 情况下可以被 async 函数外部的 catch 方法捕获到(其实此时相当于async函数返回了一个rejected状态的promise对象)。 下面代码中, async function f() { await Promise.reject(‘出错了!!‘); } f().then(v => console.log(v)).catch(e => console.log(e)) //输出: 出错了!! 任何一个 async function f() { await Promise.reject(‘出错了‘); await Promise.resolve(‘hello world‘); // 不会执行 } 有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个 async function f() { try { await Promise.reject(‘出错了‘); } catch(e) { } return await Promise.resolve(‘helloworld‘); } f().then(v => console.log(v)) //输出: helloworld ? 2.2.2、await 跟着确定的值如果 await 命令后面不是 Promise 对象,就直接返回对应的值。 async function f() { // 等同于 return 123; let a = await 123; console.log(a) } f(); //输出: 123 ? 2.3、async 函数返回的是一个 promise 对象
async function f() { return ‘hello world‘; } f().then(v => console.log(v)) // "hello world"
let p1 = new Promise((resolve,reject)=>{ resolve(‘aaa‘) }) let p2 = new Promise((resolve,reject)=>{ resolve(‘aaa‘) }) async function getUrl(url) { let response = await p1; let html = await p2; return url; } getUrl(‘http://www.baidu.com‘).then((val) => { console.log(val) }) //只有等到 p1 和 p2 都执行完毕后才会调用then里面的回调函数输出值,输出:http://www.baidu.com ? 2.3.1、async 函数的错误处理如果 async function f() { await new Promise(function (resolve,reject) { throw new Error(‘出错了‘); }); } f().then(v => console.log(v)).catch(e => console.log(e)) // Error:出错了 async function f() { await Promise.reject(‘出错了!!‘); } f().then(v => console.log(v)).catch(e => console.log(e)) //输出: 出错了!! 防止出错的方法,也是将其放在 async function f() { try { await new Promise(function (resolve,reject) { throw new Error(‘出错了‘); }); }catch (e) {} return await (‘hello world‘); //这里仍然能执行 } f().then((data) => {console.log(data);}); //输出: hello world (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |