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 ...
随机推荐
- Spring框架-AOP核心
Spring AOP AOP (Aspect Oriented Programming) 面向切面编程 OOP(Object Oriented Programming)面向对象编程,用对象的思想来完善 ...
- SpringCloud 源码学习笔记2——Feign声明式http客户端源码分析
系列文章目录和关于我 一丶Feign是什么 Feign是一种声明式. 模板化的HTTP客户端.在Spring Cloud中使用Feign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一一样的 ...
- Vue学习笔记之Vue-Router
1. 概述 Vue Router 是 Vue.js 的官方路由.它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举.功能包括: 嵌套路由映射 动态路由选择 模块化.基于组件 ...
- vitis笔记1
安装vitis2021.1 配置环境 添加环境变量 下载包 install 注意:切换到<install_dir>/Vitis//scripts/installLibs.sh,执行指令时候 ...
- python去重的几种方法
from collections import OrderedDict list1 = [1,5,2,1,10] print(list(set(list1))) #[1, 2, 10, 5] 这种方式 ...
- JavaScript查找两个节点的最近的一个共同父节点,可以包括节点自身
- EMQ X 系统调优和性能压测
前言 如果使用 EMQ 来承载百万级别的用户连接可以吗?毕竟在 MQTT 官方介绍上说 EMQ X 可以处理千万并发客户端,而 EMQ X 自己官方称 4.x 版本 MQTT 连接压力测试一台 8 核 ...
- windows10 远程桌面黑屏
[计算机配置]-[管理模板]-[Windows组件]-[远程桌面服务]-[远程桌面会话主机]-[远程会话环境]-{为远程桌面连接使用WDDM图形显示驱动程序-设置禁用}
- Django views.py 增,删,改
from django import forms from django.shortcuts import render, redirect from app01 import models # Cr ...
- 关于使用C++调用WCF的方法
因为近期要对接别人的接口,使用的是wcf,因为之前没有使用过wcf,更不了解它,于是在使用的时候出现了很多问题. 下面就记录一下下 在调用方法之前,我们一般都会拿到一个地址,http://xxxxxx ...