编程 如何使用Generator和Promise实现async/await的功能

2024-11-18 14:00:00 +0800 CST views 737

如何用Generator和Promise实现async/await的功能

思考题

请将以下async/await代码以另一种方式实现,保证异步等待功能和输出顺序一致:

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

const func = async () => {
    const data = await delay(2000, 'A');
    console.log(data);
    const res = await delay(2000, 'B');
    console.log(res);
};

func();

在继续之前,可以先自己尝试实现一下。接下来我将从async/await的基础知识开始介绍。

async/await 基本介绍

async/await是基于Promise的语法糖,能让异步代码更加简洁易读,避免繁琐的Promise链式写法。

async 关键字

async函数总是返回Promise,返回的结果可能是resolvedrejected状态。

  1. resolved 情况:

    • 如果函数有返回值,则该值被包装为Promise.resolve
    • 如果没有返回值,Promise中的值为undefined
    const func = async () => 1;
    console.log(func());  // 输出: Promise {<fulfilled>: 1}
    
  2. rejected 情况:

    • 当函数返回或抛出错误时,Promise为rejected状态。
    const func = async () => { throw new Error('error'); };
    console.log(func());  // 输出: Promise {<rejected>: Error: error}
    

await 关键字

await只能在async函数内部使用,它用于等待Promise完成,并返回其结果。

  1. resolved 情况:

    const func = async () => {
        const data = await Promise.resolve('done');
        console.log(data);  // 输出: done
    };
    
  2. rejected 情况:

    如果Promise被拒绝(rejected)且没有捕获,会抛出错误。

    const func = async () => {
        const data = await Promise.reject('error');  // 抛出错误
    };
    

如何用Generator实现 async/await 功能

为了理解async/await,我们可以借助Generator实现类似的功能。Generator是一种函数,可以在执行过程中暂停和恢复。我们通过yield来控制执行的暂停和继续。

Generator 简介

function* generatorFunc() {
    yield 1;
    yield 2;
    yield 3;
}

生成器函数返回一个迭代器对象,通过调用next()方法逐步执行:

const iterator = generatorFunc();
console.log(iterator.next());  // { value: 1, done: false }
console.log(iterator.next());  // { value: 2, done: false }
console.log(iterator.next());  // { value: 3, done: false }
console.log(iterator.next());  // { value: undefined, done: true }

Generator 与 异步操作

我们可以利用GeneratorPromise的结合来模拟async/await的行为。以下是具体的实现思路:

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

const func = function* () {
    const data = yield delay(2000, 'A');
    console.log(data);
    const res = yield delay(2000, 'B');
    console.log(res);
};

let it = func();

// 手动执行Promise链
it.next().value.then(res1 => {
    it.next(res1).value.then(res2 => {
        it.next(res2);
    });
});

这种实现方式使用了Generator来控制函数的暂停,并通过Promise来管理异步操作,从而实现与async/await类似的效果。

总结

通过这一思考题,我们可以看出async/await实际上是GeneratorPromise的语法糖。理解这些原理有助于我们更好地掌握JavaScript的异步编程模型。

复制全文 生成海报 JavaScript 编程 异步编程

推荐文章

一些好玩且实用的开源AI工具
2024-11-19 09:31:57 +0800 CST
Vue3中如何处理状态管理?
2024-11-17 07:13:45 +0800 CST
全新 Nginx 在线管理平台
2024-11-19 04:18:33 +0800 CST
php使用文件锁解决少量并发问题
2024-11-17 05:07:57 +0800 CST
Golang在整洁架构中优雅使用事务
2024-11-18 19:26:04 +0800 CST
Vue3中如何处理SEO优化?
2024-11-17 08:01:47 +0800 CST
PHP 的生成器,用过的都说好!
2024-11-18 04:43:02 +0800 CST
使用Python提取图片中的GPS信息
2024-11-18 13:46:22 +0800 CST
如何在Vue3中处理全局状态管理?
2024-11-18 19:25:59 +0800 CST
XSS攻击是什么?
2024-11-19 02:10:07 +0800 CST
IP地址获取函数
2024-11-19 00:03:29 +0800 CST
html文本加载动画
2024-11-19 06:24:21 +0800 CST
Elasticsearch 的索引操作
2024-11-19 03:41:41 +0800 CST
Vue中的`key`属性有什么作用?
2024-11-17 11:49:45 +0800 CST
阿里云发送短信php
2025-06-16 20:36:07 +0800 CST
纯CSS实现3D云动画效果
2024-11-18 18:48:05 +0800 CST
Elasticsearch 文档操作
2024-11-18 12:36:01 +0800 CST
PHP 压缩包脚本功能说明
2024-11-19 03:35:29 +0800 CST
php客服服务管理系统
2024-11-19 06:48:35 +0800 CST
一个简单的html卡片元素代码
2024-11-18 18:14:27 +0800 CST
为什么要放弃UUID作为MySQL主键?
2024-11-18 23:33:07 +0800 CST
PHP 代码功能与使用说明
2024-11-18 23:08:44 +0800 CST
程序员茄子在线接单