ES6-Promise上
一。Promise作用:解决回调地狱问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Promise 是什么</title>
<style>
* {
padding: 0;
margin: 0;
} #box {
width: 300px;
height: 300px;
background-color: red;
transition: all 0.5s;
}
</style>
</head>
<body>
<div id="box"></div> <script>
// 1.认识 Promise
// Promise 是异步操作的一种解决方案
// 回调函数
// document.addEventListener(
// 'click',
// () => {
// console.log('这里是异步的');
// },
// false
// );
// console.log('这里是同步的'); // 2.什么时候使用 Promise
// Promise 一般用来解决层层嵌套的回调函数(回调地狱 callback hell)的问题
// 运动
const move = (el, { x = 0, y = 0 } = {}, end = () => {}) => {
el.style.transform = `translate3d(${x}px, ${y}px, 0)`; el.addEventListener(
'transitionend',
() => {
// console.log('end');
end();
},
false
);
};
const boxEl = document.getElementById('box'); document.addEventListener(
'click',
() => {
move(boxEl, { x: 150 }, () => {
move(boxEl, { x: 150, y: 150 }, () => {
move(boxEl, { y: 150 }, () => {
// console.log('object');
move(boxEl, { x: 0, y: 0 });
});
});
});
},
false
);
</script>
</body>
</html>


二。实例Promise,实例的then方法,resolve和reject函数及其参数,Promise三种状态

第一个参数是成功态,第二个是失败态;

pending等待状态,箭头函数函数体里面没调用resolve 和 reject 时,只要实例一个Promise就是这个状态,可以理解为初始状态

当我们执行resolve方法后,变成成功状态 pending---fulfilled

当我们执行reject方法后,变成失败状态 pending---rejected

注意:只要promise回调函数这个实参函数体里面写了resolve()或者reject(),都可以改变状态;
const p = new Promise(function (resolve, reject) {
function fn() {
resolve()//这个位置(写在其他函数体里)写了resolve()也能将p的状态转换成成功态
};
fn();
});
console.log(p);//Promise {<fulfilled>: undefined}
如果resolve 和 reject 都在箭头函数里调用:没有成功<--->失败态之间的转变,只有初始-->成功或者初始-->失败;

Promise实例都有then方法(其实是构造函数.prototype的方法--实例可以访问原型的方法属性),p调用then方法p本身不会变

可以理解then方法内部判断p的状态,然后再内部决定调用哪个回调函数;
resolve 和 reject 方法的参数:reject 方法同理


请问三种状态指的是实例的还是构造函数的,应该指的是实例的吧?-----对!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Promise 的基本用法</title>
</head>
<body>
<script>
// 1.实例化构造函数生成实例对象
// console.log(Promise); // Promise 解决的不是回调函数,而是回调地狱
// const p = new Promise(() => {}); // 2.Promise 的状态
// const p = new Promise((resolve, reject) => {
// // Promise 有 3 种状态,一开始是 pending(未完成),执行 resolve,变成 fulfilled(resolved),已成功
// // 执行 reject,变成 rejected,已失败 // // Promise 的状态一旦变化,就不会再改变了 // // pending->fulfilled
// // resolve(); // // pending->rejected
// reject();
// }); // 3.then 方法
// p.then(
// () => {
// console.log('success');
// },
// () => {
// console.log('error');
// }
// ); // 4.resolve 和 reject 函数的参数
const p = new Promise((resolve, reject) => {
// Promise 有 3 种状态,一开始是 pending(未完成),执行 resolve,变成 fulfilled(resolved),已成功
// 执行 reject,变成 rejected,已失败 // Promise 的状态一旦变化,就不会再改变了 // pending->fulfilled
// resolve('succ');
// resolve({ username: 'alex' }); // pending->rejected
// reject('reason');
reject(new Error('reason'));
});
p.then(
data => {
console.log('success', data);
},
err => {
console.log('error', err);
}
); console.log(p);
</script>
</body>
</html>
三。实例的then方法


执行第一个回调函数

then方法内部调用哪个回调函数(then方法的两个实参)取决于调用then方法的promise实例他的状态

then里面回调函数的返回值就是Promise实例调用then方法的返回值;

then里面的异步:(挂起)



then里面的回调是异步,所以先执行打印p2;
未展开之前的状态才是执行console.log(p2)语句输出p2时的结果,即pending状态(虽然p2还没完成彻底赋值,里面的回调是异步,但是打印p2已经是promise实例了,只不过是pending状态)
展开后查看的是p2最终的结果,也就是说p2最终是会变成fulfilled状态,但是由于代码是异步执行的,所以在执行console.log(p2)输出时p2的状态为pending状态

假如程序执行时调用then的实例是pending,那这段调用then的代码会挂起,继续执行接下来要执行的同步异步等代码(挂起目的就是等待实例状态变化再来调用then,就是回头又执行),等这个实例状态变化了就会马上执行then(挂起状态结束),不论then里面的回调是否执行,这段代码不会再回头执行了;
注意,如果程序执行时,实例打点调用then,这个实例的状态确定,就不存在挂起这回事了;都是直接执行then或者跳过(比如成功态调用catch),不存在回头了
下图,程序执行p1.then时,p1此时虽然赋值还没结束,但是已经是promise实例了,只不过是pending状态


注意:return后面不是promise实例时,直接写个return 数据,不写return也是return undefined ,就相当于return new Promise(function(resolve,reject){
resolve(数据)
});------------------这就是默认用promise包装一下
且默认都是调用resolve(),所以then方法返回的是成功状态的promise实例;
return后面是promise实例时,就不会包装了;

// 1.什么时候执行
// pending->fulfilled 时,执行 then 的第一个回调函数
// pending->rejected 时,执行 then 的第二个回调函数 // 2.执行后的返回值
// then 方法执行后返回一个新的 Promise 对象
// const p = new Promise((resolve, reject) => {
// resolve();
// // reject();
// });
// const p2 = p
// .then(
// () => {},
// () => {}
// )
// .then()
// .then(); // console.log(p, p2, p === p2); // 3.then 方法返回的 Promise 对象的状态改变
// const p = new Promise((resolve, reject) => {
// // resolve();
// reject();
// });
// p.then(
// () => {
// // console.log('success');
// },
// () => {
// console.log('err'); // // 在 then 的回调函数中,return 后面的东西,会用 Promise 包装一下
// // return undefined;
// // 等价于
// // return new Promise(resolve => {
// // resolve(undefined);
// // }); // return 123;
// // return new Promise(resolve => {
// // resolve(123);
// // }); // // 默认返回的永远都是成功状态的 Promise 对象
// // return new Promise((resolve, reject) => {
// // reject('reason');
// // });
// }
// )
// .then(
// data => {
// console.log('success2', data); // // return undefined;
// return new Promise(resolve => {
// resolve(undefined);
// });
// },
// err => {
// console.log('err2', err);
// }
// )
// .then(
// data => {
// console.log('success3', data);
// },
// err => {
// console.log('err3', err);
// }
// );
注意点:调用then方法的返回值只跟then方法实参(两个回调函数)return后面的东西有关,当然我们要看看这两个回调哪个执行,不执行有return也没用;
调用then方法的返回值,我们主要关注两个:返回值promise实例的状态以及其以promise包装时resolve 或者reject 的参数;状态决定其调用then方法时then的哪个回调执行,参数的话,then的回调形参接收promise包装时resolve 或者reject 的参数;
如果连续打点调用then方法,就按照如下思路分析,不容易乱:

注意点:Promise构造器里面的回调函数里面的形参的顺序 :第一个一定是成功态,第二个一定是失败态,虽然不一定要写全形参
then里面的回调函数也是要注意顺序:第一个参数(回调函数)一定是Promise实例为成功态时被then内部调用,第二个参数(回调函数)一定是Promise实例为失败态时被then内部调用,虽然不一定要写全这两个回调函数;
四。解决回调地狱问题

重点:每一次调用movePromise会返回新的成功态p,且盒子本次达到目标位置

以下是个人更深入的理解:(挂起)

如果then中不写return,那么就相当于调用moveP后再return undefined,因为调用moveP会有过渡运动开始运动,与此同时return undefined执行,第一个实例p.then()的返回值就是默认的成功态新p马上确定了,这个p马上接着调用then方法,马上执行then的回调函数,调用moveP后再return undefined(注意此时前面then中的过度运动还没执行完毕),下一个then的移动逻辑会覆盖上一个then的效果,就会导致bug的出现。

相当于then(null,function(err){} )

直接跳过当不存在;

虽然会一直跳过往后找,失败态的实例连续一次或者多次打点调用时如果后面的then方法(catch也算是then)如果一直没有出现第二个参数,是会报错的
错误的意思就是说有个失败态的实例调用then方法一直都是无效
捕获错误就是让这个失败态实例成功调用一次then方法,让then里面的回调函数可以执行

错误提示:没有被捕获的错误;因为第一个实例是失败态,如果后面的then方法一直没有出现第二个参数(没有处理错误),是会报错的

但是成功态的实例调用then方法失效是不会报错的(then方法第一个参数为null),即使后面连续打点调用then都失效(then方法第一个参数为null),也不会报错,

跳过时的参数传递

catch方法直接看作是then方法的特例即可,一样会返回新的promise实例,和then一模一样;
前面我们想调用then方法返回一个失败态的实例,就得手动添加return new Promise(resolve,reject){reject()},在catch方法里可以使用throw,就相当于return new Promise(resolve,reject){reject(throw后面的数据)};
不仅在catch方法里。then方法也可以写throw,和catch里面用法一样


成功态实例调用then方法,如果then第一个参数为null,不会报错;如果连续打点调用then时,遇到的都是这样的then也一样不会报错,规则是遇到then第一个参数为null就直接跳过去调用下一个then
失败态实例调用then方法,then参数只有一个回调函数会报错;如果连续打点调用then时,如果所有的then都失效,会报错,如果有一个then执行了回调,那么该错误被捕获,也获得了返回值实例,如果后面接着调用then要看看返回值实例的状态,如果是失败态就得接着注意该步骤;
不论成功还是失败态,遇到失效都会跳过往下找只不过成功态找不到能执行回调的then不会报错,失败态会报错;
注意,报错不会影响后续代码的执行;

关于报错我的理解:
程序只要监测到调用了reject(),就会抛出异常,假如这个promise实例过程中调用了reject(),只要这个失败态实例打点调用then方法(例如catch)且成功执行了里面的回调函数(并没有跳过这个then),那么这个异常就消失,如果其调用then方法返回值又是一个失败态实例(返回值在实例过程中又调用了reject()),那么又会抛出异常,直到这个返回值失败态实例打点调用then方法(例如catch)且成功执行了里面的回调函数,那么这个异常就消失;
注意:捕获错误可以用then也可以用catch,catch只是特殊的then而已;
ES6-Promise上的更多相关文章
- 通过 ES6 Promise 和 jQuery Deferred 的异同学习 Promise
Deferred 和 Promise ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同.不过它们的作用可以简单的用两句话来描述 Deffered 触发 resolve ...
- Es6 Promise 用法详解
Promise是什么?? 打印出来看看 console.dir(Promise) 这么一看就明白了,Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方 ...
- ES6 Promise 全面总结
转载:点击查看原文 ES6 Promise对象 ES6中,新增了Promise对象,它主要用于处理异步回调代码,让代码不至于陷入回调嵌套的死路中. @-v-@ 1. Promise本质 Promise ...
- ES6 Promise 异步操作
最近越来越喜欢与大家进行资源分享了,并且及时的同步到自己的园子内,为什么呢? 一.小插曲(气氛搞起) 在上个月末,由于领导的高度重视(haha,这个高度是有多高呢,185就好了),走进了公司骨干员工的 ...
- 微信小程序Http高级封装 es6 promise
公司突然要开放微信小程序,持续蒙蔽的我还不知道小程序是个什么玩意. 于是上网查了一下,就开始着手开发..... 首先开发客户端的东西,都有个共同点,那就是 数据请求! 看了下小程序的请求方式大概和a ...
- 解析ES6 Promise
ES6 Promise 概念之类的,大概读者都应该有所知道,接下来我们直入终点. 先让我们来看看什么是Promise吧,他是一个object,类,arry,function? 首先,学习它的时候应该讲 ...
- ES6 Promise(2)
Promise的兴起,是因为异步方法调用中,往往会出现回调函数一环扣一环的情况.这种情况导致了回调金字塔的出现.不仅代码写起来费劲不美观,而且问题复杂的时候,阅读代码的人也难以理解. db.save( ...
- es6 promise 所见
一.Promise是什么? Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息:从本意上讲,它是承诺,承诺它过一段时间会给你一个结果. pro ...
- ES6 Promise 接口
构造函数 new Promise(function(resolve, reject){}); 构造函数接受一个函数(executor)作为参数,该函数在返回 Promise 实例之前被调用.函数的两个 ...
- ES6 promise学习
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 1.promise是一构造函数,既然是构造函数,那么我们就可以用 new Promise()得到一个p ...
随机推荐
- 解决VS2019 DevExpress工具不显示问题
一.序言 环境:NetFramework4.5,vs2019社区板 ,DevExpress 14.2.3 项目类型:winfrom 二.解决 找到DevExpress安装路径下的Bin\Framewo ...
- Redis(安装、启动、测试、环境)
Redis 概述: Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数 ...
- Mybatis Plus (特性、快速入门、日志、CRUD)
Mybatis plus 可以节省很多的工作,所有的CRUD JPA yk-mapper Mybatis plus 偷懒的 简介: MyBatis-Plus(opens new window)(简称 ...
- Vue 注册全局组件的方式
一.语法:Vue的实例.component("组件名称",组件) 1.方式一:这个组件就是 vue文件 import { createApp,h } from 'vue' //引入 ...
- 【USACO 2021 February Contest, Platinum】Problem 1 No Time to Dry
\(\text{Solution}\) 一个点可与另一个颜色相同点同时涂色当且仅当两点间颜色都大于等于这两点 那么我们可以预处理一个点向左向右最远能到的位置,记为 \(l_i,r_i)\) 当 \(l ...
- 2020-6-2 map?
问题描述 试题编号: 202006-2 试题名称: 稀疏向量 时间限制: 2.0s 内存限制: 512.0MB 问题描述: #include<stdio.h>//数据量很大,所 ...
- Vulhub 漏洞学习之:Discuz
Vulhub 漏洞学习之:Discuz 目录 Vulhub 漏洞学习之:Discuz 1 Discuz 7.x/6.x 全局变量防御绕过导致代码执行 1.1 漏洞利用过程 2 Discuz!X ≤3. ...
- key对象转换数组title
before <!DOCTYPE HTML> <html> <head> <title>key对象转换数组title</title> < ...
- PostGIS之空间连接
1. 概述 PostGIS 是PostgreSQL数据库一个空间数据库扩展,它添加了对地理对象的支持,允许在 SQL 中运行空间查询 PostGIS官网:About PostGIS | PostGIS ...
- KingbaseES DBLink 介绍
DBLink 扩展插件功能与 Kingbase_FDW 类似,用于远程访问KingbaseES 数据库.相比于Kingbase_FDW,DBLink 功能更强大,可以执行DML,还可以通过 begin ...