ES6之Promise

news2025/1/23 22:43:04

Promise是异步操作的一种解决方案

// 1.认识Promise
    document.addEventListener('click',()=>{
        console.log('这里是异步的');
    });
    console.log('这里是同步的');

Promise一般用来解决层层嵌套的回调函数(回调地狱)的问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        #box{
            width: 300px;
            height: 300px;
            background-color: red;
            transition: all .5s;
        }
    </style>
</head>
<body>
<div id="box"></div>
<script>
    // 运动
    const move=(el,{x=0,y=0}={},end=()=>{})=>{
        el.style.transform=`translate3d(${x}px,${y}px,0`;
        el.addEventListener('transitionend',()=>{
            end();
        });
    };

    const boxEl=document.getElementById('box');
    document.addEventListener('click',()=>{
        move(boxEl,{x:150},()=>{
            move(boxEl,{x:150,y:150},()=>{
                move(boxEl,{y:150},()=>{
                    move(boxEl,{x:0,y:0});
                })
            })
        })
    });
</script>
</body>
</html>

Promise的基本用法

  • 实例化构造函数生成实例对象
  • Promise的状态
// 1.实例化构造函数生成实例对象
    console.log(Promise);

    // Promise解决的不是回调函数,而是回调地狱
    //const p=new Promise(()=>{});

    // 2.Promise的状态
    const p=new Promise((resolve,reject)=>{

    });
    console.log(p);

  

Promise有3种状态,一开始是pending(未完成),执行resolve,变成fulfilled(resolved),已成功,执行reject,变成rejected,已失败

// 2.Promise的状态
    const p=new Promise((resolve,reject)=>{
        resolve();
    });
    console.log(p);

// 2.Promise的状态
    const p=new Promise((resolve,reject)=>{
        // resolve();
        reject();
    });
    console.log(p);

  

Promise的状态一旦发生变化,就不会再变化了 eg:先调用resolve()再调用reject() 状态从pending->fulfilled 之后虽然执行了reject(),但是状态不变还是fulfilled

// 2.Promise的状态
    const p=new Promise((resolve,reject)=>{
        resolve();
        reject();
    });
    console.log(p);

 

  • then方法
// 2.Promise的状态
    const p=new Promise((resolve,reject)=>{
        resolve();
    });

    // 3.then()方法
    // 第一个回调函数代表成功 第二个回调函数代表失败
    p.then(()=>{
        console.log('success');
    },()=>{
        console.log('error');
    });

控制台输出success,如果调用reject()方法,则输出error 

  • resolve和reject函数的参数
// 2.Promise的状态
    const p=new Promise((resolve,reject)=>{
        resolve({username:'jessica'});
        //reject(new Error('reason'));
    });

    // 3.then()方法
    // 第一个回调函数代表成功 第二个回调函数代表失败
    // 4.resolve()和reject()参数
    p.then((data)=>{
        console.log('success',data);
    },(err)=>{
        console.log('error',err);
    });

Promise的实例方法

then()返回的是一个新的Promise对象 

  • 什么时候执行
  • 执行后的返回值
  • then方法返回的Promise对象的状态改变(return后面的东西会用Promise包装一下
const p=new Promise((resolve,reject)=>{
        // 第一次调用resolve方法必须写 后面新的Promise对象可不写 
        resolve();
    });
    p.then(()=>{
        console.log('success1');
        // 默认返回的是 undefined
        // 默认返回的是成功状态的Promise对象
        // 不传参数的话可以不写return语句 最方便
        // return undefined;
        // 传参数的话直接return+参数 方便
        // return 123;
        // 也可以用下面的形式 源代码就是这样
        return new Promise((resolve,reject)=>{
            // resolve(undefined);
            // resolve(123);
            reject('reason');
        })
    },()=>{
        console.log('error1');
    }).then(data=>{
        console.log('success2',data);
    },err=>{
        console.log('error2',err);
    })

 

  • 向后传值
  • 使用Promise解决回调地狱
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        #box {
            width: 300px;
            height: 300px;
            background-color: red;
            transition: all .5s;
        }
    </style>
</head>
<body>
<div id="box"></div>
<script>
    // 运动
    const move = (el, {x = 0, y = 0} = {}, end = () => {
    }) => {
        el.style.transform = `translate3d(${x}px,${y}px,0`;
        el.addEventListener('transitionend', () => {
            end();
        });
    };

    const boxEl = document.getElementById('box');
    const movePromise = (el, point) => {
        return new Promise(resolve => {
            move(el, point, () => {
                resolve();
            });
        });
    };

    document.addEventListener('click', () => {
        movePromise(boxEl, {x: 150})
            .then(() => {
                return movePromise(boxEl, {
                    x: 150, y: 150
                });
            })
            .then(() => {
                return movePromise(boxEl, {
                    y: 150
                });
            })
            .then(() => {
                return movePromise(boxEl, {x: 0, y: 0});
            });
    }, false);
</script>
</body>
</html>

 

catch()方法专门用来处理rejected状态 

catch()可以捕获它前面的错误,一般总是建议,Promise对象后面要跟catch方法,这样可以处理Promise内部发生的错误

const p=new Promise((resolve,reject)=>{
        //resolve();
        reject('reason');
    });
    // 第一个then只有一个箭头函数,但是由于上面是失败状态
    // 只能通过下一次then继续寻找第二个箭头函数,如若找不到以此类推寻找
    // p.then(data=>{
    //     console.log(data);
    // }).then(null,err=>{
    //     console.log(err);
    // });

    // catch是then的特例
    // 专门捕获失败时状态
    p.then(data=>{
        console.log(data);
    }).catch(err=>{
        console.log(err);
        //默认返回undefined,成功状态的Promise对象
        // 可以制造出失败时错误
        throw new Error('reason');
    }).then(data=>{
        console.log(data);
    })

finally()方法

  • 什么时候执行
  • 当Promise状态发生变化时,不论如何变化都会执行,不变化不执行
// finally一般不接收参数
    new Promise((resolve,reject)=>{
        // resolve(123);
        reject('reason');
    }).finally(data=>{
        console.log(data);
    }).catch(err=>{
        console.log(err);
    })

 

构造函数方法

Promise.resolve()和Promise.reject()

当Promise.resolve()的参数接收的是Promise对象时,那么直接返回Promise对象,什么都不做

const p1=new Promise(resolve => {
        setTimeout(resolve,1000,'我执行了');
        // 定时器第三个参数相当于以下这种形式
        setTimeout(()=>{
            resolve('我执行了')
        },1000);
    });

    // 当Promise.resolve()接收的是Promise对象时,
    // 直接返回这个Promise对象,什么都不做
    Promise.resolve(p1).then(data=>{
        console.log(data);
    })
    // 等价于
    // p1.then(data=>{
    //     console.log(data);
    // })
    console.log(Promise.resolve(p1) === p1);//true

 控制台隔了1s后才输出我执行了

当resolve函数接收的是Promise对象时,后面的then会根据传递的Promise对象的状态变化决定执行哪一个回调

const p1 = new Promise(resolve => {
        setTimeout(resolve, 1000, '我执行了');
        // 定时器第三个参数相当于以下这种形式
        setTimeout(() => {
            resolve('我执行了')
        }, 1000);
    });

    new Promise(resolve => resolve(p1)).then(data=>{
        console.log(data);
    })

当resolve函数接收的是具有then()方法的对象时

const thenable={
        then(){
            console.log('then');
        }
    };
    Promise.resolve(thenable).then(
        data=>console.log(data),
        err=>console.log(err));
    console.log(Promise.resolve(thenable));

pending状态,所以回调一个都不会执行

要执行回调,需要以下操作

const thenable={
        then(resolve,reject){
            console.log('then');
            resolve('resolve');
        }
    };
    Promise.resolve(thenable).then(
        data=>console.log(data),
        err=>console.log(err));
    console.log(Promise.resolve(thenable));

 

reject函数:不管什么参数,都会原封不动地向后传递作为后续方法的参数

const p1 = new Promise(resolve => {
        setTimeout(resolve, 1000, '我执行了');
        // 定时器第三个参数相当于以下这种形式
        // setTimeout(() => {
        //     resolve('我执行了')
        // }, 1000);
    });

    // new Promise((resolve,reject)=>{
    //     reject('reason');
    // })
    // // 简写形式
    // Promise.reject('reason');

    Promise.reject(p1).catch(
        err => console.log(err)
    )

 

 Promise.all()

  • 关注多个Promise对象的状态变化 传入多个Promise实例,包装成一个新的Promise实例返回
  • Promise.all()的状态变化与所有传入的Promise实例对象状态有关
  • 所有状态都变成resolved,最终的状态才会变成resolved
  • 只要有一个变成rejected,最终的状态就变成rejected
const delay=ms=>{
        return new Promise(resolve => {
            setTimeout(resolve,ms);
        })
    };
    const p1=delay(1000).then(()=>{
        console.log('p1 完成了');
        return 'p1';
    });
    const p2=delay(2000).then(()=>{
        console.log('p2 完成了');
        return 'p2';
        // return Promise.reject('reason');
    });
    const p=Promise.all([p1,p2]);
    p.then(data=>{
        console.log(data);
    },err=>{
        console.log(err);
    })

Promise.race():竞赛永争第一

  • Promise.race()的状态取决于第一个完成的Promise实例对象,如果第一个完成的成功了,那最终就成功;如果第一个完成的失败了,那最终就失败
const delay=ms=>{
        return new Promise(resolve => {
            setTimeout(resolve,ms);
        })
    };
    const p1=delay(1000).then(()=>{
        console.log('p1 完成了');
        // return 'p1';
        return Promise.reject('reason');
    });
    const p2=delay(2000).then(()=>{
        console.log('p2 完成了');
        return 'p2';
    });
    const racePromise=Promise.race([p1,p2]);
    racePromise.then(data=>{
        console.log(data);
    },err=>{
        console.log(err);
    })

 

Promise.allSettled()

  • Promise.allSettled()的状态与传入的Promise状态无关,永远都是成功的
const delay=ms=>{
        return new Promise(resolve => {
            setTimeout(resolve,ms);
        })
    };
    const p1=delay(1000).then(()=>{
        console.log('p1 完成了');
        return 'p1';
        //return Promise.reject('reason');
    });
    const p2=delay(2000).then(()=>{
        console.log('p2 完成了');
        return 'p2';
    });
    const allSettledPromise=Promise.allSettled([p1,p2]);
    allSettledPromise.then(data=>{
        console.log(data);
    });

 

Promise的注意事项

  • resolve或reject函数执行后的代码(推荐在调用其函数时加上return,不再执行它们后面的代码)
  • Promise.all/race/allSettled的参数问题
  • 参数如果不是Promise数组,会将不是Promise的数组元素转变成Promise对象
Promise.all([1,2,3]).then(datas=>{
        console.log(datas);
    })
    // 相当于
    Promise.all([
        Promise.resolve(1),
        Promise.resolve(2),
        Promise.resolve(3)]
    ).then(datas=>{
        console.log(datas);
    })

 

  • 不只是数组,任何可遍历的都可以作为参数(数组、字符串、Set、Map、NodeList、arguments)
Promise.all(new Set([1,2,3])).then(datas=>{
        console.log(datas);
    })

 

  • Promise.all/race/allSettled的错误处理

Promise的应用

异步加载图片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        #img {
            width: 80%;
            padding: 10%;
        }
    </style>
</head>
<body>
<img src="https://img.mukewang.com/5e6af63d00011da318720764.jpg" alt="" id="img" >
<script>
    // 异步加载图片
    const loadImgAsync = url => {
        return new Promise((resolve, reject) => {
            const img = new Image();
            img.onload = () => {
                resolve(img);
            }

            img.onerror = () => {
                reject(new Error(`Could not load image at ${url}`));
            }
            img.src = url;
        });
    };
    const imgDOM = document.getElementById('img');
    loadImgAsync('https://2img.mukewang.com/5f057a6a0001f4f918720764.jpg')
        .then(img => {
            console.log(img.src);
            setTimeout(() => {
                imgDOM.src = img.src;
            }, 1000);
        })
        .catch(err => {
            console.log(err);
        });

</script>
</body>
</html>

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

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

相关文章

JVM垃圾回收机制、JVM垃圾回收算法、JVM CMS与G1垃圾收集,JVM内存模型

C C 需要自己回收垃圾 重复回收&#xff1a; 回收掉别人的东西 忘记回收&#xff1a; 内存泄漏 Java虚拟机做自动化回收 垃圾回收器 Root Searching&#xff08;根可达&#xff09; GC Algorithms(垃圾回收算法) Mark-Sweep(标记清除) 缺点&#xff1a;碎片化&#xff0c;一…

Lua C接口编程(一)

引言 skynet 和 openresty 都是深度使用lua的典范&#xff0c;学习lua不经要学会基本语法&#xff0c;还要学会C语言与Lua交互。lua的一大优点就是能和c/c无缝连接&#xff0c;而且可以在不需要重复编译c/c的情况下可以修改lua文件并且起作用&#xff0c;当我们的项目文件很大…

【面试题】做了一份前端面试复习计划,保熟~

大厂面试题分享 面试题库前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库前言以前我看到面试贴就直接刷掉的&#xff0c;从不会多看一眼&#xff0c;直到去年 9 月份我开始准备面试时&#xff0c;才发现很多面试经验贴…

Kubernetes(k8s) 笔记总结(二)

提示&#xff1a;针对kubernetes的工作均衡学习。 文章目录1. Kubernetes 创建资源方式2. Kubernetes 操作NameSpace3. Kubernetes的 Pod应用3.1 Pod的 解释3.2 通过命令行来创建一个pod3.3 配置文件方式创建一个Pod3.4 dashboard 可视化操作Pod3.5 针对Pod的一些细节操作3.6 P…

如何评估PMO (项目管理办公室)的实施效果?

使用有效的组织战略、方法和技术&#xff0c;可以成功启动并制度化企业范围的PMO (项目管理办公室)。 一个企业范围内的PMO可以使用成熟的技术启动。 但你应该开发和使用适当的评估工具&#xff0c;以确定你的PMO实施的项目管理过程的有效性。这些工具可以包括正式的管理评估…

黑马学ElasticSearch(四)

目录&#xff1a; &#xff08;1&#xff09;RestClient操作文档-新建文档 &#xff08;2&#xff09;RestClient操作文档-查询文档 &#xff08;3&#xff09;RestClient操作文档-更新文档 &#xff08;4&#xff09;RestClient操作文档-删除文档 &#xff08;5&#xff…

包管理工具详解npm 、 yarn 、 cnpm 、 npx 、 pnpm

1、包管理工具npm &#xff08;1&#xff09;包管理工具npm&#xff1a; Node Package Manager&#xff0c;也就是Node包管理器&#xff1b;但是目前已经不仅仅是Node包管理器了&#xff0c;在前端项目中我们也在使用它来管理依赖的包&#xff1b;比如vue、vue-router、vuex、…

数据分析-深度学习 Day4

本专栏主本专栏主要介绍和讲解李宏毅老师最新2021春季机器学习课程相关内容&#xff0c;如有记录错误&#xff0c;或理解不对&#xff0c;欢迎留言批评指正...youtube课程地址&#xff1a;&#xff08;实时更新&#xff09;ML 2021 Springspeech.ee.ntu.edu.tw/~hylee/ml/2021-…

sxs卡数据怎么恢复?分享三种恢复方案

说起sxs卡&#xff0c;你们是否有所了解呢&#xff1f;sxs卡具有很好的传输性能&#xff0c;能够存储照片和视频数据&#xff0c;主要被放置在索尼XDCAM EX型摄像机上。而在使用sxs卡设备过程中&#xff0c;难免和其他设备一样&#xff0c;容易出现数据丢失情况。而如果丢失的是…

在虚拟机上安装win11

虚拟机版本呢vmware16win11镜像&#xff1a;zh-cn_windows_11_business_editions_version_22h2_updated_dec_2022_x64_dvd_0b26ca48.isoPE镜像&#xff1a;EasyU_v3.7.iso 通过优启通工具制作两个光驱&#xff0c;第一个选pe的iso&#xff0c;第二个选win11的iso点击开启虚拟机…

(day5) 自学Java——ArrayList集合

目录 1. ArrayList 2.集合练习 (1)添加字符串和整数&#xff0c;并遍历 (2)添加学生对象并遍历 (3)查找用户是否存在 (4)返回多个数据 1. ArrayList 数组有个致命的弱点&#xff0c;那就是创建时需要指定其长度&#xff0c;并且在使用时长度不可改变。 在Java教程中知道…

[ 数据结构 ] 图(Graph)--------深度优先、广度优先遍历

0 基本介绍 为什么要有图? 无论是线性表还是树结构,局限于表示一个直接前驱和一个直接后继的关系(一对一/一对多),当我们需要表示多对多的关系时&#xff0c; 这里我们就用到了图 节点间的连接成为边,节点称为顶点,一个顶点到另一个顶点所经过的边叫路径,边有方向的叫有向图,…

js逆向-某动网演出数据获取

声明 本文仅供学习参考&#xff0c;如有侵权可私信本人删除&#xff0c;请勿用于其他途径&#xff0c;违者后果自负&#xff01; 如果觉得文章对你有所帮助&#xff0c;可以给博主点击关注和收藏哦&#xff01; 前言 目标网站&#xff1a;aHR0cHM6Ly93d3cuc2hvd3N0YXJ0LmNv…

如何远程连接Linux系统服务器

Linux服务器远程连接方法这里给大家普及一下Linux服务器&#xff0c;是一台安装Ubuntu系统的工作站。这类服务器大部分用于程序员开发编程使用&#xff0c;说简单点就是拿来敲代码的。通常需要借助远程连接工具来连接Linux远程服务器&#xff0c;如xshell&#xff1b;putty&…

PostgreSQL实战之物理复制和逻辑复制(五)

目录 PostgreSQL实战之物理复制和逻辑复制&#xff08;五&#xff09; 5 流复制主备切换 5.1 判断主备角色的五种方法 5.2 主备切换之文件触发方式 5.3 主备切换之pg_ctl promote方式 5.4 pg_rewind PostgreSQL实战之物理复制和逻辑复制&#xff08;五&#xff09; 5 流…

Vue作业

文章目录作业1作业2作业3作业4作业1 作业&#xff1a;需要用data保存&#xff1a;商品名、单价、数量&#xff0c;然后显示到页面上&#xff0c;点击按钮可以变更数量&#xff0c;最小值1&#xff0c;减按钮不可用&#xff0c;最大值20&#xff0c;隐藏按钮 总价格应该是 单价…

酒业“新物种”的新思维:用户、品牌、模式

【潮汐商业评论/原创】中国的酒文化源远流长。古人有一万种喝酒的理由&#xff0c;或聚会畅饮&#xff0c;或独酌解忧&#xff0c;而餐桌是酒最常出现的地方。如今&#xff0c;与酒相关的场景日益多元&#xff0c;往往洋溢着青春的气息。一顶帐篷&#xff0c;三两好友围坐&…

一、数据仓库基础理论

数据仓库基础理论一、数据仓库1、概念2、数据仓库分层结构3、为什么要分层二、数据集市三、数据湖1、数据湖和数据仓库一、数据仓库 1、概念 数据仓库&#xff08;Data Warehouse, DW&#xff09;&#xff1a;一个面向主题的、集成的、非易失的、反应历史变化的、用来支持企业…

哈弗品牌发布新能源越野新品类车型:H-DOG

1月6日&#xff0c;哈弗品牌新能源车型哈弗H-DOG在海口新能源车展亮相。哈弗H-DOG针对用户5天通勤、2天郊野、e享时刻三大使用场景打磨&#xff0c;满足用户“可城、可野、可电”的用车需求&#xff0c;是哈弗品牌在新能源轻越野上的全新探索。• 哈弗H-DOG采用了全新的潮野力量…

Sentinel降级策略-RT、异常比例、异常数

Sentinel降级—RT 1&#xff09;RT&#xff1a;平均响应时间&#xff1b;配置平均响应时间为200ms&#xff0c;200ms内就要将请求处理完成&#xff1b; 2&#xff09;注意&#xff1a;Sentinel 默认统计的 RT 上限是4900ms&#xff0c;超出此阈值会算作 4900ms &#xff0c;若…