Promise 类似 java 的 Callable
then 方法 类似 java 的 Future
-
PromiseA+规范(英文原文) - https://promisesaplus.com/
-
PromiseA+规范(中文) - https://www.jianshu.com/p/e0f91e03d6c1
文章目录
- # “异步” 引入
- # 定时器轮询
- # 通过文件依赖,了解任务排列
- # 禁止套娃(嵌套)
- # Promise 微任务处理机制
- # 单一状态和状态中转
- # Promise.then 也是 promise
- # return {then(resolve, reject):{...}}
- # 使用 Promise 封装 ajax 异步请求
- # Promise 错误检查 与 catch
- # 自定义 错误
- # finally
- # 例子:异步加载图片
- # 封装 setTimeOut
- # 扁平化的 setInterval
- # (优化)定时器轮询 - 解决套娃
- # 加载文件 - (Promise 形式)
- # Promise.resolve 缓存后台数据
- # Promise.all 批量获取数据
- # Promise.allSettled 状态收集
- # Promise.race 只接收最快完成的一个
- # Promise 队列原理
- # 案例:队列 ajax 、渲染
- # 语法糖 : async 、 await
- # 语法糖简化 ajax 请求
- # 案例:进度条
- # class + async 、 await
- # await 并行执行技巧
# “异步” 引入
js 会把 主线程上某些任务放入任务队列
当主线程完成后,不断轮询任务队列
function loadImag(src, resolve, reject) {
let image = new Image() ;
image.src = src ;
image.onload = resolve ;
image.onerror = reject ;
}
loadImag('./images/0fcee7d8fb636a7e86ee034ac15cc46130d404c7.jpg',() => {
console.log('图片加载完成')
}, () => {
console.log('加载失败')
}) ;
console.log('后盾热') ;
# 定时器轮询
div 向右移动,缩小
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style> div{ background-color: aqua; width: 300px; height: 300px; position: absolute; } </style>
</head>
<body>
<div></div>
<script> function interval(callback,delay=100) { let id = setInterval(() => callback(id), delay) ; } interval((id) => { const div = document.querySelector('div') ; let left = parseInt(window.getComputedStyle(div).left) div.style.left = left + 10 + 'px' ; if(left>=200) { clearInterval(id) interval((id) => { let width = parseInt(window.getComputedStyle(div).width) ; div.style.width = width - 10 + "px" ; if(width<=20) { clearInterval(id) } }) } }) </script>
</body>
</html>
# 通过文件依赖,了解任务排列
加载两个文件,hd.js 和 hd2.js
其中
hd2.js 对 hs.js 有依赖关系
但由于 加载和 加载完 两个事件是没有任务队列的。
因此会有概率出现,hd.js 加载完之前 加载了 hd2.js 。
而 hd2.js 缺少 hd.js 的依赖,从而hd2.js 报错
(如下)
function load(src,resolve) {
let script = document.createElement('script') ;
script.src = src ;
script.onload = resolve ;
document.body.append(script) ;
}
load('./dist/hd.js', () => {
show();
}) ;
load('./dist/hd2.js', () => {
console.log('hd2')
})
console.log('主进程')
hd.js
function show() {
console.log('hd show')
}
hd2.js
show() ;
所以,要让 加载和加载完 形成任务队列
需要把代码改一改
function load(src,resolve) {
let script = document.createElement('script') ;
script.src = src ;
script.onload = resolve ;
document.body.append(script) ;
}
load('./dist/hd.js', () => {// hd.js 加载完
show();
load('./dist/hd2.js', () => { // hd2.js 开始加载
console.log('hd2')
})
}) ;
console.log('主进程')
# 禁止套娃(嵌套)
下面 先开启后台服务 (我这里用 mock 工具 jsonserver - 光速使用)
开启服务:
json-server --watch db.json
db.json 数据:
{
"users": [
{"id":1, "name":"御坂美琴", "email":"jdbc@qq.com"},
{"id":2, "name":"茵蒂克丝", "email":"c3p0@qq.com"}
],
"lessons": [
{"id":1 ,"js":60, "ts":89},
{"id":2 ,"js":33, "ts":10}
]
}
ajax.js :
function ajax(url, callback) {
let xhr = new XMLHttpRequest() ;
xhr.open('GET', url) ;
// xhr.readyState==4 ==> xhr.onload
xhr.onload = function() {
if(this.status == 200) {
callback(JSON.parse(this.response)) ;
}else {
throw new Error('加载失败')
}
}
xhr.send() ;
}
index.html:
<script src="./dist/ajax.js"></script>
<script> ajax(`http://localhost:3000/users?name=御坂美琴`,(result) => { let user = result[0] ; ajax(`http://localhost:3000/lessons?id=${user.id}`, (lessons) => { console.log(lessons) }); } ); console.log('main 线程') </script>
业务完成了,但是代码一层套一层,不美观
这种套娃也有中二叫法:回调地狱
怎么避免?
# Promise 微任务处理机制
Promise 许诺
白话:等通知模式
## 状态
-
panding 待定的(准备状态)
let p = new Promise((resolve, reject)=>{ }) console.log(p) ;
-
resolved 成功状态
let p = new Promise((resolve, reject)=>{ resolve('成功状态'); }) console.log(p) ;
-
reject 拒绝状态
let p = new Promise((resolve, reject)=>{ reject('拒绝状态'); }) console.log(p) ;
## then
then 里面做处理
- value 成功参数
- reason 失败参数
let p = new Promise((resolve, reject)=>{
reject('拒绝状态');
}).then(value => {
console.log('成功的处理')
}, (reason)=> {
console.log('拒绝的处理')
})
console.log(p) ;
let p = new Promise((resolve, reject)=>{
resolve('成功状态');
//reject('拒绝状态');
}).then(value => {
console.log('成功的处理')
}, (reason)=> {
console.log('拒绝的处理')
})
console.log(p) ;
## 微任务、宏任务
<mark>同级情况下</mark>,微任务为主(优先级较高)
<script src="./dist/ajax.js"></script>
<script> let p = new Promise((resolve, reject)=>{ resolve('成功状态'); //reject('拒绝状态'); }).then(value => { console.log('微任务1:成功的处理--1') }, (reason)=> { console.log('微任务1:拒绝的处理--1') }).then(value => { console.log('微任务1:成功的处理--2') }, (reason)=> { console.log('微任务1:拒绝的处理--2') }) console.log(p) ; ajax(`http://localhost:3000/users`, (result) => { console.log('宏任务',result) }) </script>
## 宏任务、微任务执行顺序
<mark>同级下</mark>,微任务优先级高
setTimeout(()=> {
console.log('宏任务') // 宏任务等待微任务完成后执行
}, 0) ;
new Promise(resolve => {
resolve();// 把then中成功的代码放入微任务区
console.log('main promise') ;
}).then(value => {
console.log('微任务 成功') // 微任务等在同步线程完成后执行
});
console.log('main 线程完')
<mark>不同级下</mark>,顺序不变
let promise = new Promise(resolve => {
console.log("setTimeout")
resolve();
console.log('promise')
}).then(value => {
console.log('成功');
});
console.log('houdunren.,com')
# 单一状态和状态中转
如果 上级 reject ,即便下级resolve也会去到 error 回调
let p1 = new Promise((resolve, reject) => {
reject('p1 失败')
}) ;
let p2 = new Promise((resolve, reject) => {
resolve(p1) ;
}).then((value)=> {
console.log("p2 success ",value)
}, (error) => {
console.log("p2 error " , error)
})
console.log('main finish')
并且,状态确定之后,是不变的
let p2 = new Promise((resolve, reject) => {
reject("失败") ; // 确定了失败
resolve("成功") ; // 后面的这段代码想改变状态,是无法做到的
}).then((value)=> {
console.log("p2 success ",value)
}, (error) => {
console.log("p2 error " , error)
})
console.log('main finish')
# Promise.then 也是 promise
且 失败 被成功处理了, 返回的也是成功
# return {then(resolve, reject):{…}}
then 中返回 reject 结果 可以这样写(下图)
new Promise((resolve, reject)=> {
resolve("1 ok") ;
}).then(value => {
console.log(value) // 1 ok
return {
then(resolve, reject) {
reject('2 reject')
}
}
}).then(null, reason => {
console.log(reason) // 2 reject ;
})
或者
new Promise((resolve, reject)=> {
resolve("1 ok") ;
}).then(value => {
console.log(value) // 1 ok
return class {
static then(resolve, reject) {
reject('2 reject')
}
}
}).then(null, reason => {
console.log(reason) // 2 reject ;
})
原理后面说
当然,也能 写成
.... then( value => { return new Promise((resolve, reject) => reject()) }) ...
但是就很蠢
# 使用 Promise 封装 ajax 异步请求
<script src="./dist/ajax.js"></script>
<script> ajax(`http://localhost:3000/users?name=茵蒂克丝`) .then(value => { let user = value[0] ; return ajax(`http://localhost:3000/lessons?id=${user.id}`) ; }) .then(value => { console.log('ok',value); }, reason => { console.log('error', reason) ; }) </script>
js 返回 Promise 对象
function ajax(url) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest() ;
xhr.open('GET', url) ;
// xhr.readyState==4 ==> xhr.onload
xhr.onload = function(result) {
if(this.status == 200) {
resolve(JSON.parse(this.response) ) ;
}else {
reject('加载失败')
}
}
xhr.onerror = function() {
reject(this)
}
xhr.send() ;
})
}
# Promise 错误检查 与 catch
// throw new Error('promise fail')
// hd + 1 ;
resolve('rejected');
}).then(value =>
new Promise((resolve, reject)=> {
reject('失败') ;
}) ,
// reason => {}
).then(
value => {},
//reason => {}
).catch((reason) => { // 语法上,也可以放中间, 但通常放最后
console.log(reason)
}) ;
# 自定义 错误
ajax.js
class ParamError extends Error{
constructor(msg) {
super(msg) ;
this.name = 'ParamError' ;
}
}
class HttpError extends Error {
constructor(msg) {
super(msg) ;
this.name = 'HttpError' ;
}
}
class WebAssert {
static isURL(url) {
if(!/^https?:\/\//i.test(url)) {
throw new ParamError('请求地址格式错误')
}
}
}
function ajax(url) {
return new Promise((resolve, reject) => {
WebAssert.isURL(url) ;
let xhr = new XMLHttpRequest() ;
xhr.open('GET', url) ;
// xhr.readyState==4 ==> xhr.onload
xhr.onload = function(result) {
if(this.status == 200) {
resolve(JSON.parse(this.response) ) ;
}else if(this.status ==404) {
// throw new HttpError('用户不存在'); 这样是不行的,因为在新线程里面
reject(new HttpError('用户不存在'))
}else{
reject('加载失败')
}
}
xhr.onerror = function() {
reject(this)
}
xhr.send() ;
})
}
<script src="./dist/ajax.js"></script>
<script> ajax('http://localhost:3000/users1') .then(value => { console.log(value) ; }) .catch((err) => { if(err instanceof ParamError) { console.log(err.message) ; }else if(err instanceof HttpError) { alert(err.message) }else { console.log(err) } }) </script>
这里故意不存在的 请求
# finally
最终执行
例子:资源加载后,隐藏 LOADING
DOM
在·
<div id='loading'>loading...</div>
<script src="./dist/ajax.js"></script>
<script> ajax(`http://localhost:3000/users?name='茵蒂克丝'`) .then(value=> { console.log(value); }) .finally(()=> { loading.style.display='none'; }) </script>
class ParamError extends Error{
constructor(msg) {
super(msg) ;
this.name = 'ParamError' ;
}
}
class HttpError extends Error {
constructor(msg) {
super(msg) ;
this.name = 'HttpError' ;
}
}
class WebAssert {
static isURL(url) {
if(!/^https?:\/\//i.test(url)) {
throw new ParamError('请求地址格式错误')
}
}
}
function ajax(url) {
return new Promise((resolve, reject) => {
loading.style.display='block'
WebAssert.isURL(url) ;
let xhr = new XMLHttpRequest() ;
xhr.open('GET', url) ;
// xhr.readyState==4 ==> xhr.onload
xhr.onload = function(result) {
if(this.status == 200) {
resolve(JSON.parse(this.response) ) ;
}else if(this.status ==404) {
// throw new HttpError('用户不存在'); 这样是不行的,因为在新线程里面
reject(new HttpError('用户不存在'))
}else{
reject('加载失败')
}
}
xhr.onerror = function() {
reject(this)
}
xhr.send() ;
})
}
# 例子:异步加载图片
function loadImage(src) {
return new Promise((resolve, reject)=> {
const image = new Image() ;
image.src = src ;
image.onload = () => {
resolve(image)
} ;
image.onerror = reject;
document.body.appendChild(image)
})
}
loadImage('./images/0fcee7d8fb636a7e86ee034ac15cc46130d404c7.jpg')
.then(image=> {
image.style.border = 'solid 6px red'
})
# 封装 setTimeOut
function timeout(delay = 1000) {
return new Promise(resolve => {
setTimeout(resolve, delay);
})
}
timeout(2000)
.then((value) => {
console.log('定时器 - 1',value)
return timeout(2000) ;
})
.then((value) => {
console.log('定时器 - 2', value)
})
function interval(delay=1000, callback) {
return new Promise((resolve, reject) => {
let id = setInterval(() => {
callback(id, resolve);
}, delay);
})
}
interval(100, (id, resolve) =>{
console.log(12) ;
clearInterval(id) ;
resolve('定时器关闭')
}).then((value)=> {
console.log(value)
}) ;
function interval(delay=1000, callback) {
return new Promise((resolve, reject) => {
let id = setInterval(() => {
callback(id, resolve);
}, delay);
})
}
interval(100, (id, resolve) =>{
console.log(12) ;
clearInterval(id) ;
resolve('定时器关闭')
}).then((value)=> {
console.log(value)
}) ;
# (优化)定时器轮询 - 解决套娃
好,现在可以处理前面 “回调地狱” 的问题了
同样的例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style> div{ background-color: aqua; width: 300px; height: 300px; position: absolute; } </style>
</head>
<body>
<div></div>
<script> function interval(callback,delay=100) { return new Promise((resolve, reject) => { let id = setInterval(() => callback(id, resolve, reject), delay) ; }) ; } const div = document.querySelector('div') ; interval((id, resolve) => { let left = parseInt(window.getComputedStyle(div).left) div.style.left = left + 10 + 'px' ; if(left>=200) { clearInterval(id) resolve('右移完毕!') } }, 100) .then(value=> { interval((id, resolve) => { let width = parseInt(window.getComputedStyle(div).width) ; div.style.width = width - 10 + "px" ; if(width<=20) { clearInterval(id) resolve('缩小完毕!') } }) }, 100) </script>
</body>
</html>
# 加载文件 - (Promise 形式)
function loadScript(url) {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
script.src = url;
script.onload = resolve(script);
script.reject = reject;
document.body.appendChild(script)
})
}
// hd.js
// -----------------
// function show() {
// console.log('hd show')
// }
//
// hd2.js
// -----------------
// show() ;
loadScript('./dist/hd.js')
.then(script => {
console.log(script);
return loadScript('./dist/hd2.js')
}).then(script => {
console.log(script);
});
# Promise.resolve 缓存后台数据
<div id="loading">loading</div>
<script src="./dist/ajax.js"></script>
<script> function query(name) { const cache = query.cache || (query.cache = new Map()) let temp = cache.get(name) ; if(temp) return Promise.resolve(temp) ; let url = `http://localhost:3000/users?name=${name}` ; return ajax(url).then(user => { cache.set(name, user) ; return user ; }) } query('茵蒂克丝') .then(user => { console.log(user) }) setTimeout(() => { query('茵蒂克丝') .then(user => { console.log(user) }) }, 1000); </script>
# Promise.all 批量获取数据
全部成功,就成功 (下图)
function timeout(msg,delay=1000) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(msg)
}, delay);
})
}
const t1 = timeout('第一个异步') ;
const t2 = timeout('第二个异步') ;
Promise.all([t1, t2]).then(result => {
console.log(result)
})
一个失败就失败 (下图)
const t1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('第一个异步')
}, 1000);
})
const t2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('第二个异步')
}, 1000);
})
Promise.all([t1, t2])
.then(result => {
console.log('ok',result)
})
.catch(error => {
console.log('error',error)
})
失败处理了,也是成功 (下图)
const t1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('第一个异步')
}, 1000);
}).catch(error => {
console.log('第一个异步 失败')
return '1 error'
}).finally(value => {
console.log('finally')
})
const t2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('第二个异步')
}, 1000);
})
Promise.all([t1, t2])
.then(result => {
console.log('ok',result)
})
.catch(error => {
console.log('error',error)
})
## 批量 ajax 接收 (加缓存)
<script src="./dist/ajax.js"></script>
<script> function getUsers(names) { const cache = getUsers.cache ||( getUsers.cache = new Map() ) ; let promises = names.map(name => { let user = cache.get(name) ; if(user) return Promise.resolve(user) ; return ajax(`http://localhost:3000/users?name=${name}`).then(user => { cache.set(name, user) ; return Promise.resolve(user) ; }) }) return Promise.all(promises); } getUsers(['御坂美琴', '茵蒂克丝']) .then(value => { console.log(value) ; }) .catch(reason => { console.log("error", reason) }) setTimeout(() => { getUsers(['御坂美琴', '茵蒂克丝']) .then(value => { console.log(value) ; }) .catch(reason => { console.log("error", reason) }) }, 1000); </script>
# Promise.allSettled 状态收集
const p1 = new Promise((resolve, reject) => {
reject('p1 reject') ;
})
const p2 = new Promise((resolve, reject) => {
resolve('p2 resolve') ;
})
Promise.allSettled([p1, p2]).then(result => {
console.log(result)
})
## 过滤ajax请求失败数据
<script src="./dist/ajax.js"></script>
<script> function getUsers(names) { return names.map(name => { return ajax(`http://localhost:3000/users?name=${name}`) .then(user => { return user.length>0?Promise.resolve(user) : Promise.reject('炮姐找不到,只有御坂美琴') ; }) }) } Promise.allSettled(getUsers(['茵蒂克丝', '炮姐'])) .then(result => { console.log(result); }) </script>
# Promise.race 只接收最快完成的一个
看下面一个 请求超时的例子
function query(url, delay=1000) {
let promises = [
new Promise((resolve, reject)=> {
setTimeout(() => {
reject('请求超时')
}, delay);
}),
ajax(url)
]
return Promise.race(promises) ;
}
query(`http://localhost:3000/users`).then(result => {
console.log(result)
})
超时(下图)
# Promise 队列原理
## 1
function queue(num) {
let promise = Promise.resolve() ;
num.forEach(v=>{
promise=promise.then(_=>{
return new Promise(resolve => {
setTimeout(() => {
console.log(v)
resolve() ;
}, 1000);
})
})
})
}
queue([1,2,3,4,5])
## 2 优化:抽离
把 Promise 抽出来
function queue(num) {
let promise = Promise.resolve() ;
num.forEach(v=>{
promise=promise.then((value)=>{
return v(value) ;
})
})
}
function p1() {
return new Promise(resolve => {
setTimeout(() => {
console.log('p1')
resolve();
}, 1000);
})
}
function p2() {
return new Promise(resolve => {
setTimeout(() => {
console.log('p2')
resolve();
}, 1000);
})
}
queue([p1, p2])
## 优化 reduce
function queue(num) {
return num.reduce((promise, current) => {
return promise.then(current)
}, Promise.resolve());
}
function p1() {
return new Promise(resolve => {
setTimeout(() => {
console.log('ok p1')
resolve()
}, 1000);
})
}
function p2() {
return new Promise(resolve => {
setTimeout(() => {
console.log('ok p2')
resolve()
}, 1000);
})
}
queue([p1,p2])
# 案例:队列 ajax 、渲染
引入之前写好的 ajax.js
class User{
ajax(user) {
let url = `http://localhost:3000/users?name=${user}` ;
return ajax(url);
}
render(users) {
users.reduce((promise, user) => {
return promise.then(()=> {
return this.ajax(user) ;
}).then(user => {
return this.view(user);
})
}, Promise.resolve())
}
view(user) {
return new Promise(resolve => {
resolve();
let h2 = document.createElement('h2') ;
h2.innerHTML = JSON.stringify(user, null, 2)
document.body.appendChild(h2) ;
})
}
}
new User().render(['茵蒂克丝','御坂美琴']);
# 语法糖 : async 、 await
## async
在方法前 加 async
方法的返回值就 变为了 Promise
async function hd() {
return "www.houdunren.com" ;
}
let h = hd();
console.log(h) ;// 是一个 Promise 状态 resolve
h.then(v => {
console.log(v)
})
<mark>等于下面写法</mark>
function hd() {
return new Promise(resolve => {
resolve('www.houdunren.com')
})
}
let h = hd();
console.log(h) ;// 是一个 Promise 状态 resolve
h.then(v => {
console.log(v)
})
## await
async function hd() {
let name = await new Promise(resolve => {
//resolve('await') // 不放行,后面不执行
});
console.log(name);
}
hd();
其实就是 then 的简写
function hd() {
return new Promise((resolve) => {
//resolve('await'); // 不放行,后面不执行
}).then(name => {
console.log(name)
})
}
hd();
所以 可以这样写
async function hd() {
const value = 'value 0'
let value1 = await new Promise(resolve=> {
setTimeout(() => {
console.log(value)
resolve('value 1 ');
}, 1000)
})
let value2 = await new Promise((resolve)=> {
setTimeout(() => {
console.log(value1)
resolve('value 2');
}, 1000);
})
return value2;
}
hd().then(value => {
return new Promise(resolve => {
setTimeout(() => {
resolve();
console.log(value)
}, 1000);
})
})
# 语法糖简化 ajax 请求
<script src="./dist/ajax.js"></script>
<script>
async function get(name) {
let url = 'http://localhost:3000'
let user = await ajax(`${url}/users?name=${name}`)
return await ajax(`${url}/lessons?id=${user[0].id}`)
}
get('茵蒂克丝').then(value => {
console.log(value)
})
# 案例:进度条
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style> div { height: 30px; background: #8e44ad; width:0px ; display: flex; justify-content: center; align-items: center; font-size: 30px; color: #fff; } </style>
</head>
<body>
<div id="loading">0%</div>
</body>
<script src="./dist/ajax.js"></script>
<script> function query(name) { let url = `http://localhost:3000` ; return ajax(`${url}/users?name=${name}`) ; } (async ()=>{ let users = ['茵蒂克丝','御坂美琴','白井黑子','佐天泪子','初春饰利']; let len = users.length; for(let i=0;i<len;i++) { let user = await query(users[i]) ; let progress = ((i+1)/len)*100; loading.style.width = progress+'%'; loading.innerHTML = Math.round(progress)+'%' ; console.log( user.length>0?user : '没有数据' ) } })() </script>
</html>
ajax.js
<mark>这里加了延时哦,为了看出效果</mark>
class ParamError extends Error{
constructor(msg) {
super(msg) ;
this.name = 'ParamError' ;
}
}
class HttpError extends Error {
constructor(msg) {
super(msg) ;
this.name = 'HttpError' ;
}
}
class WebAssert {
static isURL(url) {
if(!/^https?:\/\//i.test(url)) {
throw new ParamError('请求地址格式错误')
}
}
}
function ajax(url) {
return new Promise((resolve, reject) => {
WebAssert.isURL(url) ;
let xhr = new XMLHttpRequest() ;
xhr.open('GET', url) ;
// xhr.readyState==4 ==> xhr.onload
xhr.onload = function(result) {
if(this.status == 200) {
resolve(JSON.parse(this.response) ) ;
}else if(this.status ==404) {
// throw new HttpError('用户不存在'); 这样是不行的,因为在新线程里面
reject(new HttpError('用户不存在'))
}else{
reject('加载失败')
}
}
xhr.onerror = function() {
reject(this)
}
setTimeout(() => {
xhr.send() ;
}, 1000);
})
}
db.json
{
"users": [
{"id":1, "name":"御坂美琴", "email":"jdbc@qq.com"},
{"id":2, "name":"茵蒂克丝", "email":"c3p0@qq.com"}
],
"lessons": [
{"id":1 ,"js":60, "ts":89},
{"id":2 ,"js":33, "ts":10}
]
}
# class + async 、 await
<mark>一个类,内部如果有 then 方法,那么,他会被包装成 Promise</mark>
不会是个坑,会了真香
例如下面(简洁啊)
## 初尝禁果
<script src="./dist/ajax.js"></script>
<script> class User { constructor(name) { this.name = name; } then(resolve, reject) { const url = `http://localhost:3000`; let user = ajax(`${url}/users?name=${this.name}`); resolve(user); } } async function get() { let user = await new User('茵蒂克丝'); console.log(user); } get(); </script>
## 异步封装在类内部
class User {
async get(name) {
const url = `http://localhost:3000`;
let list = await ajax(`${url}/users?name=${name}`);
let user = list[0];
user.name += '真平'
return user;
}
}
new User().get('茵蒂克丝').then(user => {
console.log(user)
})
# await 并行执行技巧
怎么让 await 并行?
## 方法一
await 在 接收参数时候才加上
function p1() {
return new Promise(resolve => {
setTimeout(() => {
resolve('houdunren');
}, 2000);
})
}
function p2() {
return new Promise(resolve => {
setTimeout(() => {
resolve('hdcms')
}, 2000)
})
}
async function hd() {
let h1 = p1();
let h2 = p2();
let h1value = await h1;
let h2value = await h2;
console.log(h1value, h2value)
}
hd();
async function hd() {
let res = await Promise.all([p1(), p2()]);
console.log(res)
}