ES6 学习笔记(十三)promise的简单使用
1、什么是promise
在JavaScript中,我们经常会用到回调函数,而回调函数的使用让我们没法使用return,throw等关键字。JS引用promise正好解决了这个问题。
promise单词意思是承诺,代表未来的某个事情或者是行为。promise是一个容器,包含了异步操作。因此我们认为promise是异步操作的解决方案。所有异步操作都可以通过promise来解决
2、了解promise
上面说到promise是一个容器,那我们先在控制台打印一下。
可以看到,Promise是一个构造函数,自身就有all、reject(代表失败的回调函数, 失败的操作)、resolve(代表成功的回调函数, 成功的操作)这几个于我们而言比较眼熟的方法,原型上有then、catch等同样很眼熟的方法。这么说用Promise new出来的对象肯定就有then、catch方法。
2.1、promise对象的特点
- Promise对象的状态不受外界影响。包含pending(进行中)、fulfilled(已成功)和rejected(已失败)三种状态。只有异步操作结果才可决定是哪种状态,其他任何操作都无法改变这种状态。
- 一旦状态改变,就不会再变。Promise对象的状态改变,只有两种情况:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就不会再变了,这时就称为 resolved(已定型)
举个例子:
let action = new Promise(function (resolve, reject) {
// 包含一个异步操作
setTimeout(function () {
let data = Math.floor(Math.random() * 100);
console.log(data);
if (data > 50) {
resolve({
msg: '成功',
data,
});
} else {
reject({
msg: '失败',
data,
});
}
}, 30)
});
console.log(action); // pending -- 进行中
// action -- 执行完的事件
action.then(function (d) {
// 参数1 - 成功回调
console.log(action); // resolved -- 已定型(fulfilled --- 已成功)
console.log(d);
}, function (d) {
// 参数2 - 失败回调(可选)
console.log(action); // rejected -- 已失败
console.log(d);
});
输出结果:
Promise { }
52
Promise { { msg: '成功', data: 52 } }
{ msg: '成功', data: 52 }
Promise也有一些不足的地方。其一,一旦新建Promise就会立即执行,无法取消。如果不设置回调函数,Promise内部抛出的错误不会反应到外部。其二,当处于pending状态时,无法得知目前是哪个阶段。
2.2、了解宏任务和微任务
先看个例子:
console.log("a");
setTimeout(() => console.log("b")) // 回调要等到出栈才会执行
let p = new Promise((resolve, reject) => {
resolve()
console.log("c"); // 同步代码
}).then(() => {
console.log("d"); // 异步代码
})
console.log("e"); // 同步代码
输出结果:
a
c
e
d
b
总结:
宏任务指的是click,setTimeOut等DOM事件 微任务指的是promise的异步操作,数据查询
宏任务要比微任务先进栈,但是后出栈(微任务比宏任务先执行)。因此上述代码中setTimeout函数最后执行。
3、使用promise
3.1 异步加载图片
function loadImageAsync(url){
return new Promise(function(resolve,reject){
var image = new Image();
image.onload = function(){
resolve(this)
};
image.onerror = function(){
reject(new Error('Counld not load image at'+url))
}
image.src = url
document.body.appendChild(image)
})
}
let urlimg = 'https://static.likepoems.com/cdn/sakurairo/logo.jpg'
loadImageAsync(urlimg).then(function(image){
console.log(`Image loaded:${image.src}`);
},function(error){
console.log(error);
})
3.2 使用Promise封装ajax
function getData(url) {
let promise = new Promise(function (resolve, reject) {
// 异步操作 - 做数据请求
let ajax = new XMLHttpRequest();
ajax.open('get', url);
ajax.send();
ajax.onreadystatechange = function () {
if (ajax.readyState === 4) {
if (ajax.status === 200) {
// 成功
resolve(ajax.responseText);
} else {
// 失败
reject(ajax);
}
}
}
});
return promise;
}
// 使用
getData('./1.txt').then(function (d) {
console.log(d);
console.log('成功');
}, function (err) {
console.log(err);
console.log('失败');
});
运行结果:
3.3 then方法与链式操作
举个例子:
2.txt
{
"name":"李明",
"sex":"男",
"url":"./2.txt"
}
getData('./2.txt').then(function (d) {
console.log('步骤1', JSON.parse(d).url);
return getData(JSON.parse(d).url);
}).then(function (d) {
console.log('步骤2', JSON.parse(d).url);
return getData(JSON.parse(d).url);
}).then(function (d) {
console.log('步骤3', JSON.parse(d).url);
return getData(JSON.parse(d).url);
})
输出结果:
步骤1 ./2.txt
步骤2 ./2.txt
步骤3 ./2.txt
Promise实例的then( )可以一直调用下去。
3.4 出现错误的处理
getData('./2.txt').then(function (d) {
console.log('步骤1', JSON.parse(d).url);
}).then(function (d) {
console.log('步骤2', JSON.parse(d).url);
resolve();
}).then(function (d) {
throw new Error("Error");
console.log("then");
}).catch(function (err) {
console.log("catch error:" + err.message);
});
输出结果:
步骤1 ./2.txt
catch error:Unexpected token u in JSON at position 0
总结:
若遇到异常抛出,会顺着promise链寻找下一个onRejected失败回调函数或者由catch指定的回调函数。我们一般使用catch来终止promise链,避免链条中的rejection抛出错误到全局
3.5 Promise.all()使用方法
举个例子:
let p1 = new Promise((res, rej) => {
setTimeout(() => {
res("p1")
}, 1000)
})
let p2 = new Promise((res, rej) => {
setTimeout(() => {
res("p2")
}, 2000)
})
let p3 = new Promise((res, rej) => {
setTimeout(() => {
res("p3")
}, 3000)
})
// 接收多个promise对象并返回一个promise对象
Promise.all([p1, p2, p3]).then((r) => {
console.log(r);
}).catch((err) => {
console.log(err.message);
})
输出结果:
[ 'p1', 'p2', 'p3' ]
总结: Promise.all( )实参是所有Promise实例的字面量组成的数组,执行完毕的结果是所有输出结果的所组成的数组。
4、拓展:async/await
4.1 async的使用
async函数使得异步操作变得更加方便
// async函数会返回一个Promise对象
async function hello() {
return "helloworld"
}
console.log(hello());
hello().then((r)=>{
console.log(r);
})
输出结果:
Promise { 'helloworld' }
helloworld
4.2 await的使用
await可以让代码暂停下来等待异步任务完成,await关键字只能放在async标识的异步函数里面才能够生效。
举个例子:
function getNumber() {
return new Promise((res, rej) => {
setTimeout(() => {
res(12)
}, 2000)
})
}
async function test() {
let r = await getNumber().then(v => v)
r++
return r
}
test().then(v => console.log(v))
输出结果:
13
function getNumber() {
return new Promise((res, rej) => {
setTimeout(() => {
res(12)
}, 2000)
})
}
let r = await getNumber().then(v => v)
console.log(r);
输出结果:
SyntaxError: await is only valid in async function(语法错误)
ES6 学习笔记(十三)promise的简单使用的更多相关文章
- ES6学习笔记之Promise
入职百度EFE团队实习已经三周了,实习中接触到了生产环境的技术和开发流程,大开眼界,和自己在学校接小作坊式项目是很不一样的体验.其中一个很大的感触是,ES6早已不是“选修”的尝鲜技术,而是已经全面普及 ...
- java之jvm学习笔记十三(jvm基本结构)
java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成 ...
- es6学习笔记-class之一概念
前段时间复习了面向对象这一部分,其中提到在es6之前,Javasript是没有类的概念的,只从es6之后出现了类的概念和继承.于是乎,花时间学习一下class. 简介 JavaScript 语言中,生 ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
- ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring
接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...
- ES6学习笔记<一> let const class extends super
学习参考地址1 学习参考地址2 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015:也 ...
- Go语言学习笔记十三: Map集合
Go语言学习笔记十三: Map集合 Map在每种语言中基本都有,Java中是属于集合类Map,其包括HashMap, TreeMap等.而Python语言直接就属于一种类型,写法上比Java还简单. ...
- ES6学习笔记之块级作用域
ES6学习笔记:块级作用域 作用域分类 全局作用域 局部作用域 块级作用域 全局作用域示例 var i=2; for (var i = 0; i < 10; i++) { } console.l ...
- JS&ES6学习笔记(持续更新)
ES6学习笔记(2019.7.29) 目录 ES6学习笔记(2019.7.29) let和const let let 基本用法 let 不存在变量提升 暂时性死区 不允许重复声明 块级作用域 级作用域 ...
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...
随机推荐
- shiro登录过程
工作流程: 浏览器将用户名.密码.是否记住登录等信息发送给登录controller , new UsernamePasswordToken()获取token,将用户名.加密后的密码.rememberM ...
- Spring(二)-生命周期 + 自动装配(xml) +自动装配(注解)
1.生命周期 **Spring容器的 bean **的生命周期: 1.1 默认生命周期 1.1.1 生命周期 调用构造方法,创建实例对象: set方法,给实例对象赋值: init 初始化方法 初始化对 ...
- Swift中的Result 类型的简单介绍
Swift 5引入了一个新的Result类型, 它使用枚举来处理异步函数的结果. 苹果文档对该类型的描述: A value that represents either a success or a ...
- 【设计模式】Java设计模式 - 单例模式
[设计模式]Java设计模式 - 单例模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 分享学习心得,欢迎指正,大家一起学习成长! 原创作品,更多关注我CSDN: ...
- KingbaseES应对表年龄增长过快导致事务回卷
背景 前几天碰到这样一个场景,在KingbaseES数据库当作数据同步节点.其特点是接收过来的数据量巨大,其更新超级频繁,最大的数据库达到6TB.这还不是主要的,主要导致问题发生原因是同步数据库有很多 ...
- Bypass Windows Defender Dump Lsass(手法拙劣)
0x00.前言 Windows Defender是一款内置在Windows操作系统的杀毒软件程序,本文旨在记录实战环境中,服务器存在Windows Defender情况下转储凭证的渗透手法,技术简单粗 ...
- 大根堆的pop&remove&initialize
1. 定义 [max(min) tree] 一棵树, 其中每个节点的值都大于 (小于) 或等于其 children (如果有) 的值. [max(min) heap] max(min) tree + ...
- 使用Elasticsearch Operator快速部署Elasticsearch集群
转载自:https://www.qikqiak.com/post/elastic-cloud-on-k8s/ 随着 kubernetes 的快速发展,很多应用都在往 kubernetes 上面迁移,现 ...
- centos7使用yum方式安装redis6
yum -y install epel-release wget make gcc-c++ cd /opt wget https://download.redis.io/releases/redis- ...
- CentOS yum如何安装php7.4
centos系统下使用yum安装php7.4正式版,当前基于WLNMP提供的一键安装包来安装 1.添加epel源 yum install epel-release 2.添加WLNMP一键安装包源 rp ...