SAP Fiori开发中的JavaScript基础知识14 - promise, async, await异步编程

1. 前言

本文将介绍JavaScript中异步编程技术,包括promise, sync, await的使用。

2. Promise

2.1 简介

Promise 是 JavaScript 中用于处理异步操作的一种对象。它代表了一个异步操作的最终完成(或失败)及其结果值。

Promise 对象有三种状态:

  • Pending(进行中)
  • Fulfilled(已成功)
  • Rejected(已失败)

Promise 的状态一旦改变,就不会再变,无论是从 Pending 变为 Fulfilled,还是从 Pending 变为 Rejected。

2.2 基本用法

Promise 的基本用法如下:

let oMyPromise = new Promise(function(resolve, reject) {
    // 异步操作代码
     //   xxx
     
    // 异步操作在某些条件下成功,某些条件下出错
    if (1 === 1) {
      resolve(value); // value 是异步操作返回的结果
    } else {
      reject(error); // error 是异步操作出错时的错误对象
    }
  });
  
  oMyPromise.then(function(value) {
    // 异步操作成功时执行的代码
  }, function(error) {
    // 异步操作失败时执行的代码
  });

Promise实例的构建:

  • Promise的构造函数接受一个函数作为参数, 调用构造函数得到实例oMyPromise的同时,作为参数的函数会立即执行。
  • 参数函数接受两个回调函数参数resolve和reject,在参数函数被执行的过程中,如果在其内部调用resolve,会将oMyPromise的状态变成fulfilled,或者调用reject,会将oMyPromise的状态变成rejected。

调用.then:

  • 调用.then可以为实例oMyPromise注册两种状态回调函数
  • 当实例oMyPromise的状态为fulfilled,会触发第一个函数执行
  • 当实例oMyPromise的状态为rejected,则触发第二个函数执行

2.3 代码示例

下面是一个具体的 Promise 代码示例:

let oMyPromise = new Promise(function (resolve, reject) {
  // 模拟异步操作
  setTimeout(function () {
    if (Math.random() < 0.5) { // 50% 的概率异步操作成功
      resolve('Success!');
    } else {
      reject(new Error('Failure!'));
    }
  }, 1000);
});

oMyPromise.then(function (value) {
  console.log(value); // 输出 "Success!"
}, function (error) {
  console.error(error); // 输出 Error: Failure!
});

在这个示例中,我们创建了一个新的 oMyPromise 对象,然后在 oMyPromise 的执行函数中模拟了一个异步操作。如果异步操作成功(即 Math.random() < 0.5),我们调用 resolve 函数并传入结果 ‘Success!’;如果异步操作失败,我们调用 reject 函数并传入一个新的 Error 对象。然后,我们使用 then 方法来指定异步操作成功和失败时要执行的回调函数。

2.4 链式Promise

Promise支持链式调用,若then()中的函数未返回promise参数,其会自动将其包装成一个promise。

通过链式promise,可以避免回调函数地狱(callback hell),增加异步代码的可读性。

function callBackend(oBackend) {
  return oBackend.call(); //返回一个promise
}

function processData(result) {
  return result.data;     //返回的不是promise
}

oModel.initialize()       //返回一个promise
  .then(callBackend)
  .then(processData)      //返回一个包装在promise中的值
  .then(data => console.log(data));

3. async和await

链式的promise编程风格虽然较回调函数有了更好的可读性,但这种编程方式仍然是复杂和难懂的。为了进一步简化异步编程,JavaScript中提供了关键字async和await。

async和await是用于处理异步操作的特殊关键字。它们可以让你以同步的方式编写异步代码,使得代码更易于阅读和理解。

// 传统的promise风格异步代码
function callBackend(oBackend) {
  let data1, data2;
  return oBackend.call()
    .then(data => { data1 = data })
    .then(oBackend.call())
    .then(data => { data2 = data })
    .then(() => process(data1, data2));
}

//async & await 风格
async function callBackend(oBackend) {
  let data1 = await oBackend.call();
  let data2 = await oBackend.call();
  return process(data1, data2);
}

3.1 async

async关键字用于声明一个函数是异步的,这意味着函数总是返回一个Promise。如果一个async函数返回一个值,JavaScript会自动将其包装为Promise.resolve()。如果函数抛出异常,则会被Promise.reject()捕获。

async function myAsyncFun() {
    return 'Hello, World!';
}

myAsyncFun().then(console.log); // 输出: 'Hello, World!'

3.2 await

await关键字只能在async函数内部使用。它会暂停代码的执行,直到Promise被解析,然后返回结果值。如果Promise被拒绝,await将抛出异常。

async function myAsyncFun() {
    let response = await fetch('https://api.github.com/users/github');
    let user = await response.json();
    return user.name;
}

myAsyncFun().then(console.log); // 输出: 'GitHub'

在上面的例子中,fetch函数返回一个Promise,这个Promise解析为服务器的响应。然后,我们使用await关键字等待Promise解析,然后将结果赋值给response变量。然后,我们再次使用await关键字等待response.json()的Promise解析,然后将结果赋值给user变量。

注意,如果你在没有async函数的上下文中使用await,JavaScript会抛出一个SyntaxError。

3.3 异常处理

由于await会抛出被拒绝的Promise的异常,因此你需要使用try/catch语句来处理可能的错误。

async function myAsyncFun() {
    try {
        let response = await fetch('https://api.github.com/users/github');
        let user = await response.json();
        return user.name;
    } catch (error) {
        console.error('Error:', error);
    }
}

myAsyncFun().then(console.log); // 如果请求成功,输出: 'GitHub'

在上面的例子中,如果fetch或response.json()的Promise被拒绝,catch块将捕获异常,并打印错误信息。

3.4 真实例子

一个常见的使用async和await的场景是在Web开发中从服务器获取数据。下面是一个示例,它从JSONPlaceholder API获取帖子,并打印出帖子的标题。

async function getPosts() {
    try {
        // 发送GET请求到API
        let response = await fetch('https://jsonplaceholder.typicode.com/posts');

        // 如果响应状态不是200,抛出错误
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        // 解析响应数据为JSON
        let posts = await response.json();

        // 打印每个帖子的标题
        for (let post of posts) {
            console.log(post.title);
        }
    } catch (error) {
        console.log('There was a problem with the fetch operation: ' + error.message);
    }
}

// 调用函数
getPosts();

在这个例子中,我们首先使用fetch函数发送一个GET请求到API。然后,我们检查响应的状态码是否为200(表示请求成功)。如果状态码不是200,我们抛出一个错误。然后,我们使用response.json()方法解析响应数据为JSON格式。最后,我们遍历帖子数组,打印出每个帖子的标题。

注意,我们使用try/catch语句来处理可能的错误。如果在fetch操作中发生错误(例如,网络问题或API返回非200状态码),我们将捕获错误并打印错误消息。

4. 小结

本文介绍了JavaScript中异步编程技术,包括promise, sync, await的使用,并给出了异步编程的一个真实例子。希望本文对你有帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/548960.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GitHub repository - commits - branches - releases - contributors

GitHub repository - commits - branches - releases - contributors 1. commits2. branches3. releases4. contributorsReferences 1. commits 在这里可以查看当前分支的提交历史。左侧的数字表示提交数。 2. branches 可以查看仓库的分支列表。左侧的数字表示当前拥有的分…

asyncio异步编程

参考视频&#xff1a;02 协程_哔哩哔哩_bilibili 1.协程&#xff1a;&#xff08;不是计算机中真实存在的&#xff0c;人为创造出的概念&#xff09;&#xff0c;也可称为微线程。 本质是用一个线程在一段代码中来会切换游走的线程&#xff0c;是一种用户态内的上下文切换技术…

【数据结构与算法】最大公约数与最小公倍数

最大公因数&#xff08;英语&#xff1a;highest common factor&#xff0c;hcf&#xff09;也称最大公约数&#xff08;英语&#xff1a;greatest common divisor&#xff0c;gcd&#xff09;是数学词汇&#xff0c;指能够整除多个非零整数的最大正整数。例如8和12的最大公因数…

Linux系统部署可视化数据多维表格APITable并实现无公网IP远程协同办公

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-G5XdKx1vxX0o0PES {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

说说你对集合的理解?常见的操作有哪些?

一、是什么 集合&#xff08;Set&#xff09;&#xff0c;指具有某种特定性质的事物的总体&#xff0c;里面的每一项内容称作元素 在数学中&#xff0c;我们经常会遇到集合的概念&#xff1a; 有限集合&#xff1a;例如一个班集所有的同学构成的集合无限集合&#xff1a;例如…

上网方法介绍

注册 https://www.cordcloud.biz/user 注册后先充值&#xff0c;充值后还要购买套餐&#xff0c; 充值之后&#xff0c;就可以看到流量了&#xff0c;然后复制订阅地址&#xff0c;到客户端去自动下载 URL拷贝到这个地方&#xff0c;然后点击下载

latex论文写作学习

首先无论是什么文章&#xff0c;最基础的格式都是这个&#xff1a; 如何修改字体呢&#xff1f;&#xff1a; 这样一来就可以在写完之后统一改掉了&#xff0c;用来做标记 最后记得\par 插图&#xff1a; 命令后面的中括号一般就是option

ESP32S3学习笔记(0)—— Vscode IDF环境搭建及OpenOCD调试介绍

前言 &#xff08;1&#xff09;如果有嵌入式企业需要招聘湖南区域日常实习生&#xff0c;任何区域的暑假Linux驱动/单片机/RTOS的实习岗位&#xff0c;可C站直接私聊&#xff0c;或者邮件&#xff1a;zhangyixu02gmail.com&#xff0c;此消息至2025年1月1日前均有效 &#xff…

男生穿什么裤子最百搭?适合男生穿的裤子品牌测评分享

每个伙伴们想必经常都会选择一些裤子&#xff0c;但现在市面上的裤子品牌也实在太多了&#xff0c;好不容易选到了几件好看的裤子&#xff0c;结果质量却很不好。主要就是因为现在有太多商家为了利润而使用一些舒适性、质量差的面料&#xff0c;那么今天就给大家分享一些质量上…

实战小项目 | ESP32-S3和ESP32-C3通过ESP-Mesh-Lite组网 温湿度传感器案例

传统Wi-Fi网络所有终端设备都需要直接与路由器相连&#xff0c;这使得Wi-Fi的覆盖区域受到路由器位置的限制&#xff0c;可接入终端设备的数量也受到路由器容量的限制。而乐鑫ESP-Mesh-Lite Wi-Fi组网方案&#xff0c;所有终端设备都可以与相邻设备连接&#xff0c;摆脱了对路由…

酒店水电能源计量管理系统

酒店水电能源计量管理系统是一种针对酒店行业设计的能源管理系统&#xff0c;旨在实现对水电能源的计量、监测和管理。本文将从系统特点、构成以及带来的效益三个方面展开介绍。 系统特点 1.多元化计量&#xff1a;该系统能够对酒店内的水、电能源进行多元化计量&#xff0c;…

【C++学习】map和set

目录 一、关联式容器 二、键值对 三、树形结构的关联式容器 四、set 4.1 set的介绍 4.2 set的使用 4.2.1 set的模板参数列表 4.2.2 set的构造 4.2.3 set的容量 4.2.4 set修改操作 4.2.5 set的使用举例 五、map 5.1 map的介绍 5.2 map的使用 5.2.1 map的模板参数说…

【Qt 学习笔记】Qt常用控件 | 按钮类控件Check Box的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 按钮类控件Check Box的使用及说明 文章编号&#xff1a;…

自动化测试-如何优雅实现方法的依赖

在复杂的测试场景中&#xff0c;常常会存在用例依赖&#xff0c;以一个接口自动化平台为例&#xff0c;依赖关系&#xff1a; 创建用例 --> 创建模块 --> 创建项目 --> 登录。 用例依赖的问题 • 用例的依赖对于的执行顺序有严格的要求&#xff0c;比如让被依赖的方…

揭秘智慧礼品背后的故事

如若不是从事技术行业&#xff0c;在罗列礼品清单时&#xff0c;可能不会想到 “数据”&#xff0c;但幸运的是&#xff0c;我们想到了。如何将AI技术应用到当季一些最受青睐的产品中去&#xff0c;训练数据是这一智能技术的背后动力。很多电子设备或名称中带有“智能”一词的设…

TikTok赚钱攻略 | 这6个方法你必须知道

在浩瀚的网络世界中&#xff0c;TikTok成为了一个让普通人一夜成名的舞台。Khabane Lame和Charli DAmelio就是其中的明星例子。无论是Khabane简单的肢体幽默还是Charli的舞蹈视频&#xff0c;他们都凭借TikTok赚钱&#xff0c;并且成功转变了自己的人生轨迹。他们的故事证明&am…

【kafka】安装

也是第二次安装&#xff0c;蛮记录一下 1.安装kafka之前需要先完成zookeeper的安装 【zookeeper】安装 2. Apache Kafka官网下载 3. 解压完成后修改server.properties配置文件 修改日志文件存放路径 查看与zookeeper连接的端口是否和zookeeper服务所在的端口一致 &#xf…

BTI性能开销权衡及优化措施

BTI分支目标识别精讲与实践系列 思考 1、什么是代码重用攻击&#xff1f;什么是ROP攻击&#xff1f;区别与联系&#xff1f; 2、什么是JOP攻击&#xff1f;间接分支跳转指令&#xff1f; 3、JOP攻击的缓解技术&#xff1f;控制流完整性保护&#xff1f; 4、BTI下的JOP如何…

智能助手大比拼!5款热门思维导图软件细致评估!

思维导图是一种创造性的方法&#xff0c;集思广益&#xff0c;寻找不同想法之间的联系。如果你做得好&#xff0c;你可以为难题提出新的想法和解决方案&#xff0c;总结一篇文章或演示稿&#xff0c;让你的想法井然有序。在数字时代&#xff0c;纸质思维导图存在不能随意更改、…

Nginx内存池相关源码剖析(六)外部资源释放和内存池销毁

ngx_destroy_pool函数 先执行回调函数释放所有的外部资源&#xff0c;然后free释放所有的大块内存和小块内存。 // 释放外部资源&#xff0c;销毁内存池 void ngx_destroy_pool(ngx_pool_t *pool) {ngx_pool_t *p, *n;ngx_pool_large_t *l;ngx_pool_cleanup_t *…
最新文章