zoukankan      html  css  js  c++  java
  • ES6 异步编程解决方案 之 Async

    一、async 函数的基本用法

    • async 函数返回一个 Promise 对象,可以使用 thencatch 方法 添加回调函数

    • async 函数执行时,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句 【异步函数 同步执行】

    • async 函数有很多种形式:

    // 函数声明
    async function foo() {}
    
    // 函数表达式
    const foo = async function () {};
    
    // 箭头函数
    const foo = async () => {};
    
    // Class 的方法
    class Storage {
      constructor() {
        this.cachePromise = caches.open('avatars');
      }
    
      async getAvatar(name) {
        const cache = await this.cachePromise;
        return cache.match(`/avatars/${name}.jpg`);
      }
    }
    
    // 对象的方法
    let obj = { async foo() {} };
    obj.foo().then(...)
    
    • 示例: 指定多少毫秒后输出一个值
    function timeout(ms) {
        return new Promise((resolve) => {
            setTimeout(resolve, ms);
        });
    }
    
    async function asyncPrint(value, ms) {
        await timeout(ms);
        console.log(value);
    }
    
    asyncPrint('hello world', 50);
    
    // 上面代码指定 50 毫秒以后,输出 hello world
    

    二、async 语法

    1. async 函数

    • async 函数的返回值 是 Promise 对象 (可调用 thencatch 方法)

    • async 函数内部抛出错误,会导致返回的 Promise 对象变为 reject 状态

    • async 函数的回调方法 thencatch 的参数

      • async 函数内部 return 关键字返回的值,会 作为 thencatch 方法的参数

      • async 函数的返回的 Promise 对象 状态为 resolve 时,函数内部 若没有返回值,thencatch 方法的参数 为 undefined;调用 then 方法

      • async 函数的返回的 Promise 对象 状态为 reject 时,函数内部 若没有返回值,thencatch 方法的参数 为 错误对象;调用 catch 方法

    async function f() {
        return await Promise.resolve(123);
    }
    
    f().then(v => console.log(v));  // 123
    
    async function f() {
        await Promise.resolve(123);
    }
    
    f().then(v => console.log(v));  // undefined
    
    async function f() {
      throw new Error('出错了');
    }
    
    f().then(
      v => console.log(v),
      e => console.log(e)   
    )   // Error: 出错了
    

    2. await 关键字

    • await 关键字 只能在 async 函数中使用: await 后面 如果跟异步函数,程序执行时会等 await 后面的 异步函数执行完之后,再执行 后面的代码 【异步函数 同步执行】

    • 正常情况下,await 命令后面是一个 Promise 对象;如果不是,会转成 Promise 对象,并立即 resolve

    // 只要有一个 `await` 后面的函数执行错误,程序就会停止执行代码
    
    async function f() {
        await Promise.reject('出错了');
        await Promise.resolve('hello world'); // 不会执行
    }
        
    f().then(
        (result) => {
            console.log(result);
        },
        (e) => {
            console.log(e);     
        }
    );      // 出错了
    

    三、async 应用

    1. 一个 async 函数中,有多个 await 关键字:使用 try..catch( ) 避免程序终止

    • 场景: 只要有一个 await 后面的函数执行错误,程序就会停止执行代码; async 函数返回的 Promise 对象的状态为 reject

    • 解决方案:

      • 方案 1:使用 try...catch() 把有可能出错的 操作放到 try 语句中

      • 方案 2:await 后面的 Promise 对象再跟一个 catch 方法,处理前面可能出现的错误

    // 解决方案 1:try...catch() 即使有一个异步操作失败,也不终止程序
    
    async function f() {
        try {
            await Promise.reject('出错了');
        } catch(e) {
            console.log(e);
        }
        
        return await Promise.resolve('hello world');
    }
    
    f().then(v => console.log(v))
    // hello world
    
    // 解决方案 2:catch() 即使有一个异步操作失败,也不终止程序
    
    async function f() {
        await Promise.reject('出错了')
            .catch(e => console.log(e));
        return await Promise.resolve('hello world');
    }
    
    f().then(v => console.log(v))
    // 出错了
    // hello world
    

    2. 一个 async 函数中,有多个 await 关键字:使 await 后面的异步操作 同时执行

    // 写法一
    let [foo, bar] = await Promise.all([getFoo(), getBar()]);
    
    // 写法二
    let fooPromise = getFoo();
    let barPromise = getBar();
    let foo = await fooPromise;
    let bar = await barPromise;
    

    3. 使用 try...catch() 结合 asyncawait 实现 ajax 请求轮询

    const NUM_RETRIES = 3;
    
    async function ajaxRequest() {
        for (let i = 0; i < NUM_RETRIES; ++i) {
            try {
                await $.get('http://google.com/this-throws-an-error');
                break;
            } catch(err) {
                console.log(err);
            }
        }
    }
    
    ajaxRequest();
    

    四、async for await...of ---> 异步遍历

    • 遍历时,有一个异步请求报错,都会导致程序终止;所以,结合 try...catch() 解决此类问题
    async function () {
        try {
            for await (const x of createRejectingIterable()) {
                console.log(x);
            }
        }
        catch (e) {
            console.error(e);
        }
    }
    

    五、async 与 其他异步解决方案的 比较

    • Promise: 比回调函数的写法大大改进,但是一眼看上去,代码完全都是 Promise 的 API(then、catch等等),操作本身的语义反而不容易看出来

    • Generator: 语义比 Promise 写法更清晰,需要有 任务运行器,自动执行 Generator 函数;但偏底层的写法

    • async: Generator 函数的语法糖,封装了 Generator 的底层机制 ,实现最简洁,最符合语义;

  • 相关阅读:
    Sprinig.net 双向绑定 Bidirectional data binding and data model management 和 UpdatePanel
    Memcached是什么
    Spring.net 网络示例 codeproject
    jquery.modalbox.show 插件
    UVA 639 Don't Get Rooked
    UVA 539 The Settlers of Catan
    UVA 301 Transportation
    UVA 331 Mapping the Swaps
    UVA 216 Getting in Line
    UVA 10344 23 out of 5
  • 原文地址:https://www.cnblogs.com/zxvictory/p/8548443.html
Copyright © 2011-2022 走看看