Js Promise理解和使用

news2024/11/16 15:25:54

js中的promise是一个异步编程的解决方案,语法层面上他是一个构造函数,名字为Promise()。

它的作用就是将一个任务task封装为一个Promise类的实例对象,这个对象会将任务自动运行并得到任务结果,而且在得到结果的过程中并不会影响到其他任务的进行。由此实现多个任务的并发进行。

实现异步的过程被隐藏在Promise类的实现过程中,我们只需要将任务交给Promise,Promise给我们一个instance,之后通过instance去拿任务结果就可以了。我们可以创建多个Promise类的实例instance。

一:Promise构造函数参数和基本使用介绍

1: Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。resolve和reject是两个函数,由JavaScript引擎提供,不用自己部署。

//resolve, reject名称不能修改
const promise = new Promise(function(resolve, reject) {
    // ...some code
    if ( /*异步操作成功,执行resolve方法,目的一般是将某些结果返回出去*/ ) {
        resolve(value);
    } else {
        /*异步操作失败,执行reject方法,目的一般也是将某些结果返回出去*/
        reject(error);
    }
});

2: Promise实例对象的then()方法

Promise 实例生成以后,可以用then方法分别指定resolved状态和rejected 状态的回调函数。也就是对返回的任务结果进行处理。

promise.then(resolved = function(value) {
        // success,对返回的结果value进行处理
    },
    rejected = function(error) {
        //failure,直接把错误类型报给用户
});

3:异步加载图片的例子

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ajax实操</title>
</head>
 
<body>
    <div id="box"></div>
    <script>

        //resolve, reject名称不能修改
		const promise = new Promise(function(resolve, reject) {
		    // ...some code
		    if ( /*异步操作成功,执行resolve方法,目的一般是将某些结果返回出去*/ ) {
		        resolve(value);
		    } else {
		        /*异步操作失败,执行reject方法,目的一般也是将某些结果返回出去*/
		        reject(error);
		    }
		});

        let box = document.getElementById('box');
 
        function GETJSON(url) {
            /*************************************************************/
            function ajaxTask(resolve, reject) {
                const handler = function() {
                    if (this.readystate !== 4) {
                        return;
                    }
                    if (this.status === 200) {
                        resolve(this.response);
                    } else {
                        reject(new Error(this.statusText));
                    }
                };
                const client = new XMLHttpRequest();
                client.open("GET", url);
                client.onreadystatechange = handler;
                client.responseType = "json";
                client.setRequestHeader("Access-Control-Allow-Origin", "*");
                client.send();
            }
            /*************************************************************/
            return new Promise(ajaxTask);
        };
        /*************************************************************/
        promise = GETJSON("https://www.hupu.com/home/v1/news?pageNo=4&pageSize=50");//出现ajax无法跨域的问题,目前还不会解决
 
        promise.then(
            function(data) {
                console.log(data);;
            },
            function(error) {
                box.innerHTML = '加载失败';
                console.log(error);
            }
        )
    </script>
</body>
</html>

4:有顺序的执行某些请求,我们把每个请求(promise形式)串起来搞成链式调用

//验证
function getAuth(){
    return new Promise((res,rej)=>{
        //关键代码
    })
}
//用户信息
function getUsers(){
    return new Promise((res,rej)=>{
        //关键代码
    })
}
//页面信息
function getPageInfo(){
    return new Promise((res,rej)=>{
        //关键代码
    })
}
//请求顺序:先验证 => 再拿用户 => 再拿页面信息
getAuth().then(res => {
    if(res.success){
        //验证通过,请求用户信息
        return getUsers();
    }else{
        return Promise.reject();
    }
}).then(res => {
    if(res.success){
        //成功获取用户信息,请求页面信息
        return getPageInfo();
    }else{
        return Promise.reject();
    }
}).then(res => {
    if(res.success){
        //成功获取页面信息,反射数据到视图上
 
        //over request
    }
})

5:同时发送多个并行的请求,失败的记录,成功的执行相应的逻辑

function requestMain(urls,successfn,failurefn){
    //图片url资源路径
    let urls = [
     'https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=2363246672,1942618513&fm=58',                      
     'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=4138785756047,2461366902&fm=58',           
     'https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=378711121878161,3674972757&fm=58',
     'https://ss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2412121295993728,2346220807&fm=58',
    ];
    let errorArr = [];//记录错误的信息
    //构建promise的函数
    function generatePromise(url){
        return new Promise((res,rej)=>{
            //
        })
    }
    urls.reduce((promise,url,index)=>{
        promise.then(res => {
            //请求成功执行的回调
            successfn(res);
        }).catch(err=>{
            //失败时,记录失败信息
            errorArr.push(err);
        }).then(()=>{
            if(index === urls.length-1 && errorArr.length > 1){
                //全部请求完,并且错误数组不为空时执行回调
                failurefn(errorArr);
            }else{
                promise = generatePromise(url)
            }
        })
    },
    Promise.reject(false))
}

6:避免陷入回调地狱

在这里插入图片描述
具体使用:
在这里插入图片描述
在这里插入图片描述
(1) 首先定义三个url的地址;获取第一个url,通过getData(),它return new Promise也就是return一个promise的class的实例。
(2) getData(url1).then 这个then就是new Promise里面的方法,.then(data1 => {console.log(data1) return getData(url2)})。data1就是我们通过url1获取的数据,然后打印出来,这个地方直接return getData(url2),直接return,然后就直接可以再后面.then,我们看data2,然后return getData(url3),.then,最后.catch,它是一个防错处理,万一那一层遇到问题,就会触发error这个回调函数,就会触发catch。
(3) 写法上.then .then .then…… .then都是单层的,是一个管道形式,就是一节对应一节,一节对应一节,它不是一个嵌套形式,不像回调地狱那样,一层一层嵌套。
(4) promise里面还是一个callback的形式,但是它把callback的形式变成了非嵌套的形式,变成了管道式的串联的形式,这就是一个进步,一串一串的形式,串联着走,永远都是一层,这就是promise的一个形式。

二:理论理解

promise是浏览器引擎自带的(但不是所有浏览器都支持promise)
在这里插入图片描述
promise的参数是一个函数且必须有这个函数,否则报错,姑且命名为A函数;

let p = new Promise()
console.log(p); // TypeError: Promise resolver undefined is not a function

A函数里有两个参数,这两个参数也是函数。res和rej这两个参数都是函数,名字随意。
res是成功时的回调
rej是失败时的回调

在这里插入图片描述
new Promise函数是同步函数,并且是立即执行的

promise共有三种状态,pending,fulfilled,rejected

  • 状态只能从pending变为fulfilled状态,成功状态。
  • 或者从pending变为rejected状态,失败状态。

例如:pending转变到fulfilled,状态就确定了,只能是fulfilled状态;如果想转成rejected状态,是不能转的。

当promise刚new出来时,是pending状态:
在这里插入图片描述
promise函数对象有三个属性,如上图展示的,[[Prototype]]其实就是是__ proto__;其他两个属性如下:

PromiseState:就是promise的现在状态:

当你调用res函数,状态立马变为fulfilled(成功状态)
在这里插入图片描述
当你调用rej函数,状态立马变为rejected(失败状态)
在这里插入图片描述
如果两个状态都存在,以谁先调用为准:
在这里插入图片描述

PromiseResult :res或rej返回的结果

PromiseResult就是res或rej执行后的返回的结果,是返给then的。
在这里插入图片描述
当你new 一个promise时,就已经开始自动执行函数。promise是同步的,但then是异步的,要注意区分

promise实例原型上的then函数:

在这里插入图片描述
res函数和rej函数返回的数据,谁来接收的,用then函数

then函数里的参数是两个异步回调函数,是异步的哈,第一个参数函数用于接收res返回来的数据,第二个参数函数用于接收rej返回的数据。

then的第一个参数函数里的形参用来接收res返回的数据:
在这里插入图片描述
then的第二个参数函数里的形参用来接收rej返回的数据:
在这里插入图片描述

其实then里面的函数就是res和rej
在这里插入图片描述
如果new promise中没有写res或rej 则then里的函数不会执行:

let p = new Promise((res,rej)=>{
	
})
p.then(val=>{
	console.log(11); // 11不输出
})

then的返回值:

(1) 如果(父级)上一个then返回的是数据或undefined,则(子级)下个then的状态为成功状态,并将父级返回值返回到子级then的参数里面:

let p = new Promise((res,rej)=>{
	res(11)
})
// 父级then
let p1 = p.then(val=>{
	console.log(val); // 11
	// 默认是return undefined
})
// 子级then ,then中的参数是上一个then返回的值,
p1.then(value=>{
	console.log(value); // undefined
})

在这里插入图片描述

(2) 如果父级then返回的是一个数据:

let p = new Promise((res,rej)=>{
	res(11)
})

let p1 = p.then(val=>{
	console.log(val);
	return {name:'wyy'}
})

p1.then(value=>{
	console.log(value);
})

在这里插入图片描述
(3) 如果父级then抛出的是一个错误,则父级then的状态为失败状态,并将失败状态的值返回给子级then:

通过throw主动抛出错误或者代码出现错误,则promise的状态为rejected,值为throw的值;或者代码出错也为rejected状态,例如输出一个不存在的a;console.log(a)。

第二个then的promise实例状态是根据p.then的返回值决定的

在这里插入图片描述
在这里插入图片描述
如果没有return,则默认为undefined,即是fulfilled状态。

catch

catch是处理rej函数的。当返回错误时调用catch:
在这里插入图片描述
当new promise出现rej(), throw, 语法错误以上三种形式式,就会调用catch函数。

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

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

相关文章

区间预测 | MATLAB实现Lasso分位数回归时间序列预测

区间预测 | MATLAB实现Lasso分位数回归时间序列预测 目录 区间预测 | MATLAB实现Lasso分位数回归时间序列预测效果一览基本描述模型描述程序设计学习总结参考资料效果一览 基本描述 LASSO回归的特点是在拟合广义线性模型的同时进行变量筛选(variable selection)和复杂度调整(…

D2. RGB Substring (hard version)(尺取)

Problem - 1196D2 - Codeforces 通用领域 医学 计算机 金融经济 你有一个包含n个字符的字符串s&#xff0c;每个字符是R&#xff0c; G或B。 你还得到一个整数k。你的任务是改变初始字符串s中的最小字符数&#xff0c;这样在改变之后&#xff0c;将会有一个长度为k的字符串…

C语言及算法设计课程实验三:最简单的C程序设计——顺序程序设计(一)

C语言及算法设计课程实验三&#xff1a;最简单的C程序设计——顺序程序设计一、实验目的二、 实验内容2.1、实验内容1&#xff1a;通过下面的程序掌握各种格式转换符的正确使用方法三、 实验步骤3.1、顺序程序设计实验题目1&#xff1a;通过下面的程序掌握各种格式转换符的正确…

[OC学习笔记]启动流程

我们的app是如何从桌面图标被启动的嘞&#xff1f;这个问题值得探究。 冷启动与热启动 这两个启动的区别其实很简单&#xff0c;就看启动之前手机后台是否有app存活。 名称区别冷启动启动时&#xff0c;App的进程不在系统里&#xff0c;需要开启新进程。热启动启动时&#x…

前端学习笔记006:React.js

&#xff08;前面学了那么多&#xff0c;终于到 React 了~&#xff09; React.js 大家应该听说过&#xff0c;是用于构建前端网页的主流框架之一。本文会把 React.js 开发中会用到的东西&#xff08;包括 React 核心&#xff0c;React 脚手架&#xff0c;React AJAX&#xff0…

nodejs接收时get请求参数

在http协议中&#xff0c;一个完整的url路径如下图 通过下图我们可以得知&#xff0c;get请求的参数是直接在url路径中显示。 get的请求参数在path资源路径的后面添加&#xff0c;以?表示参数的开始&#xff0c;以keyvalue表示参数的键值对&#xff0c;多个参数以&符号分…

Typescript中函数类型

不给参数定义类型&#xff0c;会报错&#xff0c;如下&#xff1a; 常见写法 function add1(x: number, y: number) {return x y; }function add1_1(x: number, y: number): number {return x y; }const add2 function (x: number, y: number): number {return x y; };con…

第一天作业

第一天 配置ansible学习环境实现以下要求1.控制主机和受控主机通过root用户通过免密验证方式远程控住受控主机实施对应&#xff08;普通命令&#xff0c;特权命令&#xff09;任务2.控制主机连接受控主机通过普通用户以免密验证远程控住受控主机实施指定&#xff08;普通命令&…

【Wayland】QtWayland启动流程分析

QtWayland启动流程分析 QtWayland版本&#xff1a;6.4.0 QtWayland的服务端(CompositorServer)入口点是QWaylandCompositor这个类&#xff0c;可以参考官网提供的example&#xff0c;其路径为&#xff1a;examples\wayland\minimal-cpp 下面基于minimal-cpp这个例子&#xff…

详解 Redis 中的 AOF 日志

AOF&#xff08;Append Only File&#xff09;追加写&#xff0c; AOF 日志它是写后日志&#xff0c;“写后”的意思是 Redis 是先执行命令&#xff0c;把数据写入内存&#xff0c;然后才记录日志&#xff0c;如下图所示&#xff1a; 后写日志有什么好处呢&#xff1f; Redis …

FPGA知识汇集-串行 RapidIO: 高性能嵌入式互连技术

本文摘自&#xff1a;德州仪器网站 串行RapidIO: 高性能嵌入式互连技术 | 德州仪器 (http://ti.com.cn) 串行RapidIO针对高性能嵌入式系统芯片间和板间互连而设计&#xff0c;它将是未来十几年中嵌入式系统互连的最佳选择。 本文比较RapidIO和传统互连技术的优点&#xff1b…

Windows内核--GUI显示原理(6.1)

传统的Windows图形处理 在Vista之前&#xff0c;图形子系统内核部分win32k.sys 通过DDI接口操作显示驱动&#xff0c; 显示驱动通过ENG接口调用win32k.sys. From: Windows 2000 显示体系结构 显示驱动程序的作用 不同显示驱动程序负责对于不同显示设备的优化。GDI仅负责标准位图…

使用python的parser.add_argument()在卷积神经网络中如何预定义参数?

在训练卷积神经网络时&#xff0c;需要预定义很多参数&#xff0c;例如batchsizebatch_sizebatchs​ize,backbone,dataset,datasetrootbackbone,dataset,dataset_rootbackbone,dataset,datasetr​oot等等&#xff0c;这些参数多而且特别零散&#xff0c;如果我们最初不把这些参…

我国制造行业 工业控制系统安全控制措施建设思考总结

声明 本文是学习GB-T 32919-2016 信息安全技术 工业控制系统安全控制应用指南. 下载地址 http://github5.com/view/585而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 工业控制系统安全控制概述 从概念上来说&#xff0c;工业控制系统的安全与其它领域…

【网络】网络发展,网络协议,网络传输流程,地址管理

目录 1.计算机网络背景 1.1网络发展 局域网和广域网 1.2 协议 2.网络协议初识 2.1协议分层 2.2OSI七层模型 2.3 TCP/IP 五层&#xff08;或四层&#xff09;模型 网络和操作系统之间的关系 2.4重谈协议 -- 计算机的视角&#xff0c;如何看待协议&#xff1f; 2.5 网…

python带你采集淘/苏/唯/考四大电商平台商品数据

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 环境介绍: python 3.8 越稳定越好 pycharm 2021专业版 一、苏宁 模块使用: selenium >>> pip install selenium 3.141.0 Python当中的模块 操作 浏览器的驱动 Chrome浏览器 Chromedr…

2023北京国际残疾人用品展览会|福祉博览会

全 称&#xff1a;2023中国国际福祉博览会暨中国国际康复博览会 英 文&#xff1a;Care & Rehabilitation Expo China 2023 时 间&#xff1a;2023年5月21-23日 地 点&#xff1a;北京首钢会展中心&#xff08;1-3号馆&#xff09; 主 办&#xff1a;中国残疾人联合会 承 办…

visdrone数据集转化为MOT数据集(用作MOTR模型训练)

文章目录visdrone数据集转化为MOT数据集MOT17 数据集格式traindet.txtgt.txtseqinfo.initestdet.txtvisdrone——Task 4_ Multi-Object Tracking配置seqinfo.ini文件代码如下Linuxvisdrone数据集转化为MOT数据集 MOT17 数据集格式 ├── MOT17 │ ├── images │ ├─…

YOLO学习记录之模型修改

我们在做实验时&#xff0c;不免需要对模型结构进行修改来检测自己的改进性能&#xff0c;对于一般模型而言&#xff0c;我们只需要简单的在代码中添加网络层即可&#xff0c;但对于一些预训练好的模型&#xff0c;我们则需要进行较为复杂的修改。以我们的YOLOV7模型为例&#…

[Linux]----守护进程

文章目录前言一、什么是守护进程?二、会话和进程组会话进程组三、守护进程的编程流程总结前言 这节课我来给大家讲解在Linux下如何让进程守护化,运行在后台,处理我们的任务. 正文开始! 一、什么是守护进程? 守护进程也称为精灵进程(Daemon),是运行在后台的一种特殊进程.它…