解决异步回调:Promise/async与await修饰符

595 阅读4分钟

Promise

Promise支持链式调用,可以解决回调地狱问题。

Promise简介

  • Promise对象可以解决回调地狱的问题
  • Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大
  • Promise可以理解为一个容器,里面可以编写异步程序的代码
  • 从语法上说,Promise 是一个对象,使用的使用需要 new

基本使用

  1. promise 是一个对象,使用的时候需要new

  2. 在new promise的时候,必须要传递一个回调函数

  3. 返回了一个promise对象,里面包含一个方法 then()

  4. 回调函数中

    • 回调函数中可以接收形参 callback 只要发现在回调函数中调用了 callback => 说明then方法被调用
    • 写自己的业务逻辑-异步
    • 异步操作完成了,调用callback函数
  1. callback被调用了;then方法才可以触发
const p1 = new Promise(function (callback) {
    console.log('Prom被new啦,异步代码 settimeout');
    setTimeout(() => {
        console.log('数据返回了');
        callback({ meta: '请求成功' })
    }, 1000)
})
p1.then(res => {
    console.log('p1 then方法输出了');
    console.log(res);
})

完整使用

promise 内置了两种操作 成功 => resolve => 调用函数 => .then 失败 => reject => 调用函数 => .catch 调用了resolve, .then方法才会触发 调用了reject, .catch方法才会触发

const p1 = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        let result = { code: 200, mas: '接口没有权限' }
        // 判断成功或失败
        if (result.code === 200) {
            resolve({ meta: '请求成功' })
        } else {
            reject({ meta: '请求失败' })
        }
    }, 1000)
})
​
p1.then(res => {  
    console.log('成功时调用');
    console.log(res);
}).catch(err => {
    console.log('失败时调用');
    console.log(err);
})

三种状态

  • 最初状态:pending,等待中,此时promise的结果为 undefined;

  • 当 resolve(value) 调用时,达到最终状态之一:fulfilled,(成功的)完成,此时可以获取结果value

  • 当 reject(error) 调用时,达到最终状态之一:rejected,失败,此时可以获取错误信息 error

image.png

当达到最终的 fulfilled 或 rejected 时,promise的状态就不会再改变了。

then的链式调用

关于 promise对象,可以一直then下去

then函数:1.创建promise对象;2.返回这个promise对象

如果在then函数中 return 数据回去,那么就可以在下一个then函数中获取到这个值

const p1 = new Promise(resolve => {
    resolve()
})
​
p1.then(() => {
    console.log(1);
    return 22
})
    .then(res => {
        console.log(res);
        return 33
    })
    .then(res => {const p1 = new Promise(resolve => {
    resolve('我不调用,then不会触发')
})
​
p1.then(res => {
    console.log(res);
    const p2 = new Promise(resolve => {
        setTimeout(() => {
            resolve('返回的对象一定是promise')
        }, 1000)
    })
    return p2
})
    .then(res => {
        console.log(res);
        const p3 = new Promise(resolve => {
            setTimeout(() => {
                resolve('只有resolve调用了,then才会触发')
            }, 1000)
        })
        return p3
    })
    .then(res => {
        console.log(res);
    })
        console.log(res);
        return 44
    })
    .then(res => {
        console.log(res);
    })

同步异步

new Promise是同步执行的

获取结果时(调用 resolve 触发 then方法时)是异步的

// 输出结果是:1;2;5;3
console.log(1);
​
// new promise  里面的代码是同步执行
const p1 = new Promise(resolve => {
    console.log(2);
    resolve(3)
})
​
// promise then 方式是异步的执行
p1.then(res => {
    console.log(res);
})
​
console.log(5);

promise的封装

调用了resolve就可以触发then

then方法可以返回数据 -> promise对象

function sleep(num) {
    const p2 = new Promise(resolve => {
        setTimeout(() => {
            resolve(num)
        }, 1000)
    })
    return p2
}
​
const p1 = sleep(1)
​
p1.then(res => {
    console.log(res);
    return sleep(2)
})
    .then(res => {
        console.log(res);
        return sleep(3)
    })
    .then(res => {
        console.log(res);
        return sleep(4)
    })
    .then(res => {
        console.log(res);
        sleep(res)
    })

async 和 await 修饰符

用来解决异步回调的终极解决方案

  • async 用于修饰一个 function

    • async 修饰的函数,总是返回一个 Promise 对象
    • 函数内的返回值,将自动包装在 resolved 的 promise 中
  • await 只能出现在 async 函数内

    • await 让 JS 引擎等待直到promise完成并返回结果
    • 语法:let value = await promise对象; // 要先等待promise对象执行完毕,才能得到结果
    • 由于await需要等待promise执行完毕,所以await会暂停函数的执行,但不会影响其他同步任务
  • 对于错误处理,可以选择在async函数后面使用 .catch() 或 在promise对象后使用 .catch()

错误处理

function sleep(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (num !== 2) {
                resolve(num)
            } else {
                reject('后端去吃饭了')
            }
        }, 1000)
    })
}
// ----------------------  通过 then 获取结果   --------------------------------
sleep(1)
    .then(res => {
        console.log(res);
        return sleep(2)
    })
    .then(res => {
        console.log(res);
        return sleep(3)
    })
    .then(res => {
        console.log(res);
        return sleep(4)
    })
    .then(res => {
        console.log(res);
    })
    .catch(err => {
        console.log(err);
    })
// ---------------------- 通过 async/await 获取结果 ----------------------------
async function init() {
    // try 里面放正常的代码
    // 当有错误时,会执行catch里面的代码
    try {
        const res1 = await sleep(1)
        console.log(res1);
        const res2 = await sleep(2)
        console.log(res2);
        const res3 = await sleep(3)
        console.log(res3);
        const res4 = await sleep(4)
        console.log(res4);
    } catch (error) {
        console.log(error);
    }
}
init()