Promise之async 与 await

一,async 函数

通过在函数声明前加上async关键字,可以将任何函数转换为返回Promise的异步函数。这意味着你可以使用.then().catch()来处理它们的结果。

<script>
    let result = async function myFn() {
        return 521
    }
    //Proise的链式调用
    result().then((res)=>{ 
        console.log(res) // 521
    },(reason)=>{
        console.log(reason)
    })
</script>

⏰ async 修饰的函数返回一个非Promise对象时,  函数调用时产生的Promise对象的状态为‘fulfilled’, 结果值为返回的值

🌰示例

<script>
    let result = async function myFn() {
        //1. 如果返沪值是一个非Promise类型的数据
        return 521  //result() 返回的Promise对象的结果值,取决这个值。result() 返回的Promise的对象的状态为‘fulfilled’
    }
    console.log(result());
</script>

结果

 

⏰ async 修饰的函数返回一个Promise对象时,函数调用时产生的Promise对象的结果值和状态取决这个Promise对象

🌰示例一:成功

<script>
    let result = async function myFn() {
        //1. 如果返沪值是一个Promise类型的数据
        return new Promise((resolve,reject)=>{
            resolve('ok') //状态为成功,值为ok
        })
    }
    console.log(result());
</script>

结果

 🌰示例二:失败

<script>
    let result = async function myFn() {
        //1. 如果返沪值是一个Promise类型的数据
        return new Promise((resolve, reject) => {
            reject('error') //状态为失败,值为error
        })
    }
    console.log(result());
</script>

结果

 🌰示例三:抛出异常

<script>
    let result = async function myFn() {
        //1. 如果返沪值是一个Promise类型的数据
        return new Promise((resolve, reject) => {
            throw 'error' //状态为失败,只为‘error'
        })
    }
    console.log(result());
</script>

结果

⏰ async 修饰的函数抛出异常时,函数调用时产生的Promise对象的状态为‘rejected’, 结果值为抛出异常的值

🌰示例

<script>
    let result = async function myFn() {
        throw '抛出异常'
    }
    console.log(result());
</script>

结果

🔉 总结:async 修饰的函数,调用时返回的Promise对象状态和结果值,给then方法很类似。

二,await 表达式

🔉 await 右侧的表达式一般为 promise 对象, 但也可以是其它的值。

注意

1. await 必须写在 async 函数中, 但 async 函数中可以没有 await。

2.await关键字可以暂停async函数的执行,等待Promise的解决(resolve),然后以Promise的值继续执行函数。

async function asyncFunction() {
  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("完成"), 1000)
  });
  let result = await promise; // 等待,直到promise解决 (resolve)
  console.log(result); // "完成"
}

asyncFunction();

3. 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理。

 

⏰ 1. 如果表达式是 promise 对象, await 返回的是 promise 成功的值

🌰示例一:成功态

<script>
    let result = async function myFn() {
        //1.定义一个Promise 对象
        let p = new Promise((resolve, reject) => {
            resolve('ok')
        })
        //2.await使用
        let res = p
        console.log(res);
    }
    result()
</script>

结果

🌰示例二:失败态

<script>
    let result = async function myFn() {
        //1.定义一个Promise 对象
        let p = new Promise((resolve, reject) => {
            reject('error')
        })
        //2.await使用
        //⚠️假如promise对象是失败的状态,需要try catch 才能获取错误值.
        try {
            let res = await p
        } catch (error) {
            console.log(error); 
        }
    }
    result()
</script>

结果

🌰示例三:抛出异常

<script>
    let result = async function myFn() {
        //1.定义一个Promise 对象
        let p = new Promise((resolve, reject) => {
            throw '抛出异常'
        })
        //2.await使用
        //⚠️假如promise对象是失败的状态,需要try catch 才能获取错误值.
        try {
            let res = await p
        } catch (error) {
            console.log(error); 
        }
    }
    result()
</script>

结果

 

⏰ 2. 如果表达式是其它值, 直接将此值作为 await 的返回值

<script>
    let result = async function myFn() {
        //1.定义一个非Promise 对象
        let x = 20
        let y = 10
        //2.await使用
        let res = await (x + y)
        console.log(res)
    }
    result()
</script>

结果

三,async 与 await 结合实践

🔉 async/await的目的是为了简化使用基于promise的API时所需的语法。

1. 基础用法

async函数返回一个Promise,而await关键词可以暂停async函数的执行,等待Promise解决。

async function myFn() {
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('ok')
        }, 2000)
    })
    let data = await p //等待,直到promise解决 (resolve)
    console.log(data) //完成 ‘ok’
}

2. 错误处理

使用try...catch结构处理async/await中的错误。

async function myFn() {
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            // resolve('ok')
            reject('抛出异常')
        })
    })

    try {
        let result = await p
        console.log(result) //resolve 时 ‘ok’
    } catch (error) {
        console.log(error) //reject 时 ‘抛出异常’
    }
}

3. 并行执行

Promise.all()可以用来并行执行多个await操作。

async function myFn(urls) {
    const promises = urls.map(url => fetch(url).then(r => r.json()));
    return await Promise.all(promises);
}

4. 条件异步

根据条件执行await

async function fetchData(condition) {
    if (condition) {
        return await fetch('url');
    }
    return 'No fetch needed';
}

5. 循环中的await

在循环中使用await时,每次迭代都会等待。

async function sequentialStart(urls) {
    for (const url of urls) {
        const response = await fetch(url);
        console.log(await response.json());
    }
}

6. 异步迭代器

对于异步迭代器(例如Node.js中的Streams),可以使用for-await-of循环。

async function processStream(stream) {
    for await (const chunk of stream) {
        console.log(chunk);
    }
}

7. await之后立即解构

直接在await表达式后使用解构。

async function getUser() {
    const { data: user } = await fetch('user-url').then(r => r.json());
    return user;
}

8. 使用默认参数避免无效的await

如果await可能是不必要的,可以使用默认参数避免等待。

async function fetchData(url = 'default-url') {
    const response = await fetch(url);
    return response.json();
}

9. await在类的方法中

在类的方法中使用async/await

class DataFetcher {
    async getData() {
        const data = await fetch('url').then(r => r.json());
        return data;
    }
}

10. 立刻执行的async箭头函数

可以立即执行的async箭头函数。

(async () => {
    const data = await fetch('url').then(r => r.json());
    console.log(data);
})();

11. 使用async/await进行延时

利用async/await实现延时。

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedLog(item) {
    await delay(1000);
    console.log(item);
}

12. 使用async/await处理事件监听器

在事件处理函数中使用async/await

document.getElementById('button').addEventListener('click', async (event) => {
    event.preventDefault();
    const data = await fetch('url').then(r => r.json());
    console.log(data);
});

13. 以顺序方式处理数组

使用async/await以确定的顺序处理数组。

async function processArray(array) {
    for (const item of array) {
        await delayedLog(item);
    }
    console.log('Done!');
}

14. 组合async/awaitdestructuring以及spread运算符

结合使用async/await,解构和展开操作符。

async function getConfig() {
    const { data, ...rest } = await fetch('config-url').then(r => r.json());
    return { config: data, ...rest };
}

15. 在对象方法中使用async/await

async方法作为对象的属性。

const dataRetriever = {
    async fetchData() {
        return await fetch('url').then(r => r.json());
    }
};

16. 异步生成器函数

使用async生成器函数结合yield

async function* asyncGenerator(array) {
    for (const item of array) {
        yield await processItem(item);
    }
}

17. 使用顶级await

在模块顶层使用await(需要特定的JavaScript环境支持)。

// ECMAScript 2020引入顶级await特性, 部署时注意兼容性
const config = await fetch('config-url').then(r => r.json());

18. async/await与IIFE结合

async函数与立即执行函数表达式(IIFE)结合。

(async function() {
    const data = await fetch('url').then(r => r.json());
    console.log(data);
})();

19. 使用async/await优化递归调用

async function asyncRecursiveFunction(items) {
    if (items.length === 0) return 'done';
    const currentItem = items.shift();
    await delay(1000);
    console.log(currentItem);
    return asyncRecursiveFunction(items);
}

20. 在switch语句中使用await

switch语句的每个case中使用await

async function fetchDataBasedOnType(type) {
    switch (type) {
        case 'user':
            return await fetch('user-url').then(r => r.json());
        case 'post':
            return await fetch('post-url').then(r => r.json());
        default:
            throw new Error('Unknown type');
    }
}

四,async 与 await 结合发送 AJAX 请求

function sendAjax(url) {
    return new Promise((resolve,reject) => {
       const xhr = new XMLHttpRequest();
       xhr.open('get',url);
       xhr.send();
       xhr.onreadystatechange = function () {
           if(xhr.readyState === 4) {
               if(xhr.status>=200 && xhr.status < 300){
                     resolve(xhr.response);
               } else {
                     reject(xhr.status);
               }
           }
       }
    })
}

async function main() {
   let a = await sendAjax('https://api.apiopen.top/api/sentences');
    console.log(a);
}
main();

posted on 2024-07-15 13:52  梁飞宇  阅读(67)  评论(0)    收藏  举报