Promise的总结

news2024/12/23 13:33:19

Promise的总结

(1)什么是同步,异步?

同步表示需要前一个任务完成之后,才会执行下一个任务,简而言之,就是上一行代码执行返回结果后,才会执行下一行代码(好理解)

异步表示异步任务启动后,会继续向下执行,等到同步代码执行结束之后才执行回调函数;

//异步执行
    function func1() {
            console.log('start');
            setTimeout(()=>{
                console.log('i am callback');
            },3000);
            console.log('end');

        }
//这个函数会先执行console.log('start')-,接着执行setTimeout(),但是setTimeout()里面的回调函数是一个异步函数,所以先放起来,继续执行后面的console.log('end');然后发现所有的同步代码执行完毕后,再去执行setTimeout()里面的回调函数,这里需要注意的是不是不执行setTimeout,而是里面的异步的回调函数不执行
// 因此 打印的顺序为 start end 然后等3秒之后打印出 i am callback

(2)回调函数

回调函数是ES5里面解决异步顺序的一种方法,但是这种方法的可读性很差,当出现回调函数层层嵌套的情况时,可维护性差,可读性差,也就是出现了所谓的回调地狱。

    function fn(cb) {
        setTimeout(() => {
            cb();
        }, 1000);
    }

    fn(function () {  // 回调地狱 ;
        console.log(111);
        fn(function () {
            console.log(222);
            fn(function () {
                console.log(333);
                fn(function () {
                    console.log(444);
                })
            })
        })
    })

如何解决回调地狱的问题呢:

(1)Es6中的Promise

(2)async await

(3)观察者模式

(3)Promise

resolve和reject方法

1.pending 没有任何操作
2.resolved/fulfilled 成功的状态
3.rejected 失败的状态

    function fn(){
        let  p = new Promise((resolve,reject)=>{
        })
        console.log(p);
    }

在这里插入图片描述

//  resolve()函数的作用就是将PromiseState从pending状态更新为fulfilled的状态,resolve(param)的参数会作为[[PromiseResult]]的值
function fn1(){
        let  p = new Promise((resolve,reject)=>{
            resolve()
        })
        console.log(p);
    }

function fn2(){
        let  p = new Promise((resolve,reject)=>{
            resolve(123)
        })
        console.log(p);
    }

resolve()
resolve(124)

//  reject()函数的作用就是将PromiseState从pending状态更新为 rejected的状态, rejected(param)的参数会作为[[PromiseResult]]的值
function fn1(){
        let  p = new Promise((resolve,reject)=>{
             reject(param)
        })
        console.log(p);
    }

then方法

每一个promise对象都会有一个then方法
then方法里有2个回调函数,onResolved和onRejected。

1.onResolved: 在调取 resolve函数的时候执行  (then里的第一个回调函数)
            promiseState : fufilled 状态的时候
            promiseResult: 作为 onResolved函数的参数; 
 2.onRejected : 在调取reject 函数的时候执行;(then里的第二个回调 函数);
             promiseState : rejected 状态的时候
             promiseResult: 作为 onRejected函数的参数;

1.onResolved回调函数 参数 是promiseResult的结果值;

代码如下:

  /* 
    调用 resolve 的时候  promiseState 变成 fufilled状态  
    promiseResult 是传递的参数 data
   */
    function fn(){
        let p = new Promise((resolve, reject) => {
            const data = '1234'
            resolve(data);
        })
        console.log(p);
        p.then(function (res) {   // 是成功状态的promise对象的promiseResult结果值;
            console.log("onResolved执行了", res);
        }, function () {
            console.log("onRejected执行了");
        });
    }
    

在这里插入图片描述

//  resolve函数在异步回调里面,所以先执行同步语句,然后在执行异步语句,所以执行同步语句console.log(p)的时候,还没有执行resolve,p的状态还是pending,然后在多
function fn(){
        let p = new Promise((resolve, reject) => {
            
            setTimeout(() => {
                const data = '1234'
                resolve(data);
                // reject("错误");
            }, 2000);

        })
        console.log(p);
        p.then(function (res) {   // 是成功状态的promise对象的promiseResult结果值;
            console.log("onResolved执行了", res);
        }, function () {
            console.log("onRejected执行了");
        });
    }

在这里插入图片描述

catch方法

在这里插入图片描述

如果catch之前的任意一个阶段发生了错误,那么就会触发catch,之后的then就不会被执行,这个和同步编程里面用到的try…catch…块很相似。

Promise用法技巧

(1)

在这里插入图片描述

上面这种写法会打破两个promise的并行,他会等到第一个任务执行完毕之后才执行第二个任务,更高效的写法是用promise.all组合起来,然后再去 await,修改后的程序运行效率会提升一倍。

在这里插入图片描述

(2)如果我们希望等待循环中所有的异步操作都执行完毕后再继续执行后面的代码,是不能直接使用forEach或者map这一类方法的,如下图,尽管我们在回调函数中写了await,但是这里的forEach会立刻返回,他并不会暂定等到所有的异步方法都执行完毕。

在这里插入图片描述
如果我们希望等待循环中所有的异步操作都执行完毕后再继续执行后面的代码,正确的写法还是应该使用传统的for循环。
在这里插入图片描述
更进一步,如果我们想要循环中的所有操作都并发执行的话,一种更炫酷的写法就是使用for await,
在这里插入图片描述

重点,宏任务,微任务,同步,异步,Event Loop模型以及执行顺序

js是单线程(自上而下执行代码),因此一个任务时间过长,势必会造成线程堵塞,影响渲染效率;

随着Promise的引入,JavaScript引擎自身也能够发起异步任务了,于是,js任务就分为了同步任务和异步任务,异步任务由进一步划分为 宏任务微任务,所以说宏任务微任务都是异步任务的范畴。

微任务执行比较快,一次可以执行很多个,在当前宏任务执行后立刻清空微任务可以达到伪同步的效果,这对视图渲染效果起到至关重要的作用,这也是区分宏任务、微任务的原因。

宏任务的微任务的基本类型

new Promise()内部的代码是同步任务

宏任务:setTimeout(), setInterVal() ,异步Ajax请求

微任务:Promise.then(), Promise.catch()和Promise.finally(),process.nextTick()

宏任务和微任务执行过程

先执行同步代码,遇到异步宏任务就放到宏任务队列中,遇到异步微任务就放到异步微任务队列中,当所有的同步代码执行完毕后,将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环到所有的任务执行完毕。

console.log('1');
 
setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})
setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})
1)执行第一行的同步任务,打印1

2)第一个setTimeout加入任务队列宏任务区,记为s1

3)第15行的process.nextTick是异步任务中的微任务,加入微任务区,记为n1

4)第18行的promise是同步任务,打印7,其后的.then是微任务,加入微任务区,记为t1

5)第24行的setTimeout加入任务队列宏任务区,记为s2。至此,同步代码执行完毕。

6)执行微任务区中的任务,n1打印6,t1打印8。至此,微任务区任务执行完成

7)执行宏任务区s1,打印2,其内process.nextTick放入微任务区,记为n2,其后promise为同步任务,立即执行打印4,将后续.then微任务放入微任务区记为t2

8)继续执行微任务区,n2打印3,t2打印5

9)执行第二个setTimeout,直接打印9,其内process.nextTick放入微任务区,记为n3,其后promise为同步任务,立即执行打印11,将后续.then微任务放入微任务区记为t3

10)执行微任务,n3打印10,t3打印12

最终打印结果为:1、7、6、8、2、4、3、5、9、11、10、12

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Security 6.1.x 系列(5)—— Servlet 认证体系结构介绍

一、前言 本章主要学习Spring Security中基于Servlet 的认证体系结构,为后续认证执行流程源码分析打好基础。 二、身份认证机制 Spring Security提供个多种认证方式登录系统,包括: Username and Password:使用用户名/密码 方式…

如何给echarts的legend设置不同的样式和位置 legend分组显示

legend分组显示 给每一个图例设置不一样的位置和样式 样式如下 demo代码 option {title: {text: Stacked Line},tooltip: {trigger: axis},// legend写为数组可以给一些给某些组分配一些不一样的样式legend: [{data: [// 使用svg画任意的图形{name:Email,icon: path://"…

【Linux】gcc和g++

👦个人主页:Weraphael ✍🏻作者简介:目前正在学习c和Linux还有算法 ✈️专栏:Linux 🐋 希望大家多多支持,咱一起进步!😁 如果文章有啥瑕疵,希望大佬指点一二 …

Java日志技术

什么是日志 日志技术 概述 日志技术的体系、Logback日志框架的概述 Logback快速入门 Logback设置日志级别

Python教程75:Pandas中DataFrame数据的修改操作

1.DataFrame数据结构的特点包括: 表格型的数据结构,具有行和列。 每一列的标签值允许使用不同的数据类型。 每个数据值都可以被修改。 结构的行数、列数允许增加或者删除。 有两个方向的标签轴,分别是行标签和列标签。 可以对行和列执行算术运…

基于springboot实现高校食堂移动预约点餐系统【项目源码】计算机毕业设计

基于springboot实现高校食堂移动预约点餐系统演示 Java语言简介 Java是由SUN公司推出,该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称,也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备…

springboot2.0 集成swagger3+Knife4j导出离线API 配置

springboot 版本2.3.1 一、集成swagger3 引入swagger依赖包 <!--swagger3集成--><dependency><groupId>org.springframework.plugin</groupId><artifactId>spring-plugin-core</artifactId><version>2.0.0.RELEASE</version>…

最新yolov8环境搭建、推理训练一站式超详细教学

1、获取yolov8源码 访问yolov8_github官网&#xff0c;网络不稳定时可能需要加速器。yolov8源码地址 获取方式&#xff1a;直接下载或者git工具克隆 我使用git操作进行演示&#xff0c;复制github上的地址(需提前关闭加速器)。 git clone https://github.com/ultralytics/ul…

arduino的API函数

API在这里&#xff1a;Arduino Reference - Arduino Reference 我觉得一天是不可能学的完的&#xff0c;这么多呢 我现在觉得&#xff1a;不用去学习这些API&#xff0c;以后碰到再去看好了

Java基于协同过滤算法开发的springboot+vue服装商城

演示视频 https://www.bilibili.com/video/BV1oH4y127fq/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 主要功能&#xff1a;用户可以浏览商品和特价商品&#xff0c;加入购物车&#xff0c;直接下单支付&#xff0c;在我的个人中心里可以管理自己的…

鸿蒙 ark ui 网络请求 我不允许你不会

前言&#xff1a; 最近有在学习这个鸿蒙的ark ui开发 因为鸿蒙不是发布了一个鸿蒙next的测试版本 明年会启动纯血鸿蒙应用 所以我就想提前给大家写一些博客文章 效果图 11-24 16:26:22.005 25156-25156/com.example.httpsrequest E A0ff00/HTTPS: 请求状态 --> 200, %{pub…

C语言猜素数(ZZULIOJ1292:猜素数)

题目描述 Lx给Xp出了一道难题&#xff0c;随便在0和1000000之间抽出两个数&#xff0c;估计在这两个数之间的素数的个数&#xff0c;如果猜测的结果和正确结果一样&#xff0c;Xp就可以得到Lx的一件礼物&#xff0c;你能猜对吗&#xff1f;编程实现一下吧&#xff01; 输入&…

探索 Vue 中的 bus.$emit:实现组件通信的强大工具

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

ref详解(C#)

本质上来说 ref 的就是把 C/C 指针的那一套又拿回来了&#xff0c;而且还封装成一套自己的玩法。 我想设计者的初心把 ref 的功能限制得死死的&#xff0c;可能也考虑到 C# 是一门面向业务开发的语言&#xff0c;讲究的是做项目快狠准&#xff0c;性能反而不是第一要素&#x…

AIGC原理:扩散模型diffusion综述一:面向视觉计算的扩散模型研究进展

论文地址&#xff1a;State of the Art on Diffusion Models for Visual Computing &#x1f449; 贴一幅SGM&#xff08;Score-based Generative Model&#xff09;的原因是宋飏博士将他2019年提出的SMLD模型和2020年Jonathan Ho提出的DDPM采用SDE进行一统这两大极为相似的生成…

免费不限字数的文本转语音AI配音工具,无需安装

上周给大家分享了AI绘本故事制作&#xff0c;很多小伙伴让我&#xff0c;推荐一款免费的AI配音&#xff0c;音色质量富有情感语调&#xff0c;而且手机上就能用的文本转语音工具。 OK&#xff0c;那么今天就给小伙伴们推荐一款我经常自用的AI配音工具&#xff0c;无需安装下载&…

【教学类-06-10】20231125(55格版)X-Y之间“乘法×题”(以1-9乘法口诀表为例)(随机抽取和正序抽取)

图片展示 &#xff08;随机打乱排序&#xff09; 正序&#xff08;每张都一样&#xff09; 背景需求&#xff1a; 2023年11月24日&#xff0c;准备了一些题目&#xff0c;分别给大4班孩子介绍“5以内加法、5以内减法、5以内加减混合”““10以内加法、10以内减法、10以内加减…

【数据结构】什么是队列?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;队列的定义 &#x1f4cc;队列的抽象数据类型 &#x1f4cc;队列的顺序存储结构 &#x1f4cc;队列的链式存储结构 结语 人生,是一个又一个小小的队列…

【数据结构】树与二叉树(廿六):树删除指定结点及其子树(算法DS)

文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点4. 删除结点及其左右子树a. 逻辑删除与物理删除b. 算法DSTc. 算法解析d. 代码实现递归释放树算法DS e. 算法测试 5. 代码整合…

Multi-Modal Meta Continual Learning

⊙ \odot ⊙denotes the modulation operator&#xff0c;Cont. is the continuum data 辅助信息 作者未提供代码