Promise 类似 java 的 Callable
then 方法 类似 java 的 Future

  • 下一篇: 《JS - 16 - 任务调度、宏任务、微任务、轮询》

  • PromiseA+规范(英文原文) - https://promisesaplus.com/

  • PromiseA+规范(中文) - https://www.jianshu.com/p/e0f91e03d6c1

  • 视频:https://www.bilibili.com/video/av82587599?p=22

文章目录

  • # “异步” 引入
  • # 定时器轮询
  • # 通过文件依赖,了解任务排列
  • # 禁止套娃(嵌套)
  • # Promise 微任务处理机制
    • ## 状态
    • ## then
    • ## 微任务、宏任务
    • ## 宏任务、微任务执行顺序
  • # 单一状态和状态中转
  • # Promise.then 也是 promise
  • # return {then(resolve, reject):{...}}
  • # 使用 Promise 封装 ajax 异步请求
  • # Promise 错误检查 与 catch
  • # 自定义 错误
  • # finally
  • # 例子:异步加载图片
  • # 封装 setTimeOut
  • # 扁平化的 setInterval
  • # (优化)定时器轮询 - 解决套娃
  • # 加载文件 - (Promise 形式)
  • # Promise.resolve 缓存后台数据
  • # Promise.all 批量获取数据
    • ## 批量 ajax 接收 (加缓存)
  • # Promise.allSettled 状态收集
    • ## 过滤ajax请求失败数据
  • # Promise.race 只接收最快完成的一个
  • # Promise 队列原理
    • ## 1
    • ## 2 优化:抽离
    • ## 优化 reduce
  • # 案例:队列 ajax 、渲染
  • # 语法糖 : async 、 await
    • ## 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.onloadxhr.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) ;

## 微任务、宏任务

同级情况下,微任务为主(优先级较高)

  <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>

## 宏任务、微任务执行顺序

同级下,微任务优先级高

    setTimeout(()=> {console.log('宏任务') // 宏任务等待微任务完成后执行}, 0) ;new Promise(resolve => {resolve();// 把then中成功的代码放入微任务区console.log('main promise') ;}).then(value => {console.log('微任务 成功') // 微任务等在同步线程完成后执行});console.log('main 线程完')

不同级下,顺序不变

    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 okreturn {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 okreturn 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.onloadxhr.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.onloadxhr.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.onloadxhr.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)})

# 扁平化的 setInterval

    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 状态 resolveh.then(v => {console.log(v)})

等于下面写法

    function hd() {return new Promise(resolve => {resolve('www.houdunren.com')})}let h = hd();console.log(h) ;// 是一个 Promise 状态 resolveh.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
这里加了延时哦,为了看出效果

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.onloadxhr.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

一个类,内部如果有 then 方法,那么,他会被包装成 Promise

不会是个坑,会了真香

例如下面(简洁啊)

## 初尝禁果

<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)}

JS - 15 - 异步、Promise、async、await相关推荐

  1. Promise async/await的理解和用法

    Promise && async/await的理解和用法 为什么需要promise(承诺)这个东西 在之前我们处理异步函数都是用回调这个方法,回调嵌套的时候会发现 阅读性 和 调试 的 ...

  2. ES6箭头函数以及promise/async/await测试案例

    ES6箭头函数的运用 下面以一段代码解释 function one(){return 1 以上函数用箭头函数写步骤,参考下面代码 {}和里面的东西先删去 one = (里面写参数/无参数的里面为空)= ...

  3. [C#] 谈谈异步编程async await

    [C#] 谈谈异步编程async await 转载于:https://www.cnblogs.com/macT/p/9288112.html

  4. js callback promise async await 几种异步函数处理方式

    ***callback  这个是最常用的也是最简单的 ,比如在ajax网络请求中,返回请求完成返回的数据 回调函数就是把一个函数当成另一个函数的参数,可以传递函数内的局部变量,也可以异步完成一些操作, ...

  5. async js 返回值_JS异步编程 | Async / Await / Generator 实现原理解析

    async/await实现 在多个回调依赖的场景中,尽管Promise通过链式调用取代了回调嵌套,但过多的链式调用可读性仍然不佳,流程控制也不方便,ES7 提出的async 函数,终于让 JS 对于异 ...

  6. rust异步编程--理解并发/多线程/回调/异步/future/promise/async/await/tokio

    1. 异步编程简介 通常我们将消息通信分成同步和异步两种: 同步就是消息的发送方要等待消息返回才能继续处理其它事情 异步就是消息的发送方不需要等待消息返回就可以处理其它事情 很显然异步允许我们同时做更 ...

  7. JS实现sleep,普通版+promise+async/await

    1-1 普通版 function sleep() {var start = new Date()while(new Date() - start <= sleepTime) {}var t1 = ...

  8. js异步函数(async/await)

    1.概念 异步函数也称为"asynac/await"(语法关键字),是ES6期约模式在ECMAScript函数中的应用.async/await是ES8新增的.这个特性让以同步方式写 ...

  9. angular2 学习笔记 ( Rxjs, Promise, Async/Await 的区别 )

    Promise 是 ES 6 Async/Await 是 ES 7 Rxjs 是一个 js 库 在使用 angular 时,你会经常看见这 3 个东西. 它们都和异步编程有关,有些情况下你会觉得用它们 ...

最新文章

  1. 【转载】C# 获取系统时间及时间格式
  2. 大数据如何改变商业管理
  3. c语言探测次数不超过4的哈希算法,HihoCoder1084: 扩展KMP(二分+hash,求T串中S串的数量,可以失配一定次数)...
  4. Java集合篇:Map总结
  5. linux第一次防火墙
  6. SpringCloud使用汇总Config
  7. Hive操作语句实例讲解(帮助你了解 桶 bucket)
  8. 开发人员在编写 HTML 和 CSS 时最常犯的六大错误
  9. 我的世界f服务器自定义皮肤,我的世界服务器皮肤指令
  10. win10连Android机,Windows10电脑可以和安卓手机无缝连接使用了,实用性干翻Mac-win10手机...
  11. MessageBox用法详解(c++)
  12. html 卫星地图显示地名,卫星图看:河南10个名字非常好听的县(区),你认识几个?...
  13. 深度解析,马斯克最新发射的先进火箭
  14. 大神论坛 史上最全植物大战僵尸分析及游戏辅助Python实现
  15. 基于微信小程序的教学评价平台开发
  16. mysql占用cpu特别高的解决_mysql占用CPU过高的解决办法
  17. WPF 基于 WER 注册应用崩溃无响应回调和重启方法
  18. Annotation定义
  19. UWP ComboBox 样式的问题及改善
  20. 工业控制系统安全评估流程威胁事件构建

热门文章

  1. linux打开文件慢,Linux 文件打开过多 (Too many open files)
  2. 为svn添加hook脚本
  3. python中字符串定义及特性
  4. 利用无线物联网控制器实现无线位移测量
  5. 《机械制造业智能工厂规划设计》——2.1 智能工厂设计流程
  6. 苹果steam手机令牌未能连接服务器,steam手机令牌登不上怎么办(6种原因方法轻松解除)...
  7. 人大金仓应邀参加第三届全国水力学与水利信息大会
  8. pug模板引擎基本用法
  9. 巅峰极客第一场CTF部分writeup
  10. Scala基础练习题1