Promise 是异步编程
的一种解决方案,它允许你以一种同步的方式编写异步代码
promise
:承诺、保证
ES6 - Promise
JS 是通过回调函数来实现异步编程的,当异步操作多了以后,就会产生回调嵌套回调的问题,这就是回调地狱
Promise 方式:将异步操作以同步操作的方式表达出来,避免了层层嵌套的回调函数
Promise 新建后立即执行
封装一个 Promise fs.readFile('./a' , (err, data ) => { if (err) return console .log('读取错误' ) console .log(data.toString()) fs.readFile('./b' , (err, data ) => { if (err) return console .log('读取错误' ) console .log(data.toString()) fs.readFile('./a' , (err, data ) => { if (err) return console .log('读取错误' ) console .log(data.toString()) }) }) }) function readFile (path ) { const p = new Promise ((resolve, reject ) => { fs.readFile(path, (err, data ) => { if (err) return reject(err) resolve(data.toString()) }) }) return p } readFile('a' ) .then((res ) => { console .log(res) return readFile('a' ) }) .then((res ) => { console .log(res) return readFile('b' ) }) .then((res ) => { console .log(res) })
promise 的三个状态
then、catch 和 finally
说明:获取异步操作的结果
then()
:用于获取异步操作成功时的结果 -> resolve
catch()
:用于获取异步操作失败时的结果 -> reject
finally()
:方法用于指定不管 Promise 对象最后状态如何,都会执行的操作,finally方法的回调函数不接受任何参数
说明:then()
方法可以有多个,按照先后顺序执行,通过回调函数返回值传递数据给下一个 then
p .then((value ) => { console .log('文件a的内容为:' , value) }) .catch((err ) => { console .log('文件读取失败:' , err) }) p.then( (value) => { }, (err) => { } )
all 和 race MDN-Promise.all() MDN-Promise.race()
let p1 = new Promise ((resolve, reject ) => { setTimeout (() => { resolve('成功1' ) },500 ) }) let p2 = new Promise ((resolve, reject ) => { setTimeout (() => { resolve('成功2' ) },1500 ) }) let p3 = new Promise ((resolve, reject ) => { setTimeout (() => { reject('失败' ) }, 1000 ) }) Promise .all([p1, p2]).then(res => { console .log(res) }) Promise .all([p1, p2, p3]).then(res => { console .log(res) }).catch(error => { console .log(error) }) Promise .race([p1, p2]).then((res ) => { console .log(res) }, (error ) => { console .log(error) }) Promise .race([p1, p3]).then((res ) => { console .log(res) }, (error ) => { console .log(error) }) Promise .race([p2, p3]).then((result ) => { console .log(res) }, (error ) => { console .log(error) })
async 和 await
async / await 用同步编写代码的方式 处理异步操作的一个方案
async:修饰 (修饰一个内部有异步操作的函数) 格式 : async + 函数 (里面有异步操作的函数)
await : 等待 (等上一个异步操作完成啊 , 修饰 一个结果是 promise 的)异步操作 格式 : await + 异步操作(结果 promise 对象)
async 和 await 是成对出现的,await 只能在 async 函数中使用
function readFile (path ) { const p = new Promise ((resolve, reject ) => { fs.readFile(path, (err, data ) => { if (err) { return reject(err) } resolve(data.toString()) }) }) return p } async function fn ( ) { try { const res1 = await readFile('./data/a1.txt' ) console .log(res1) } catch (error) { console .log(error) } const res2 = await readFile('./data/b.txt' ) console .log(res2) const res3 = await readFile('./data/c.txt' ) console .log(res3) } fn()
function sleep (a, b ) { const p = new Promise ((resolve, reject ) => { setTimeout (() => { resolve(b) }, a) }) return p } async function fn ( ) { const res1 = await sleep(1000 , 'a' ) console .log(res1) const res2 = await sleep(5000 , 'b' ) console .log(res2) const res3 = await sleep(3000 , 'c' ) console .log(res3) } sleep(1000 , 'a' ) .then((res ) => { console .log(res) return sleep(5000 , 'b' ) }) .then((res ) => { console .log(res) return sleep(3000 , 'c' ) }) .then((res ) => { console .log(res) }) const p1 = Promise .all([sleep(1000 , 'a' ), sleep(5000 , 'b' )])p1.then((res ) => { console .log(res) }) const p2 = Promise .race([sleep(1000 , 'a' ), sleep(5000 , 'b' )])p2.then((res ) => { console .log(res) })
Promise.try() 实际开发中,经常遇到一种情况:不知道或者不想区分,函数f是同步函数还是异步操作,但是想用 Promise 来处理它。因为这样就可以不管f是否包含异步操作,都用then方法指定下一步流程,用catch方法处理f抛出的错误。
Promise .resolve().then(f)
上面的写法有一个缺点,就是如果f是同步函数,那么它会在本轮事件循环的末尾执行。
const f = () => console .log('now' )Promise .resolve().then(f)console .log('next' )
用async函数
(async () => f())() .then(...) .catch(...)
Promise.try方法
const f = () => console .log('now' )Promise .try(f)console .log('next' )
new Promise 和 Promise.resolve()