Promise学习笔记
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise学习笔记相关的知识,希望对你有一定的参考价值。
注:笔记来自于视频尚硅谷Web前端Promise教程从入门到精通
注:如果是初学仅需要学会Promise的基本使用即可,不要陷入要自己实现手写Promise中。
Promise的理解和使用
Promise是什么
- Promise是一门新的技术,ES6技术规范。
- Promise是javascript进行异步编程的新解决方案。旧方案是单纯使用回调函数。
- 从语法上来说,Promise是一个构造函数。
- 从功能上来说,promise对象用来封装一个异步操作并可以获取其成功和失败的结果值。
JavaScript中常见的异步编程场景有:
- fs模块文件操作:
require('fs').readFile('./test.txt', (err,data)=>);
- 数据库操作
- Ajax:
$.get('/server', (data)=>);
- 定时器:
setTimeout(()=>, 2000);
Promise的出现解决了回调地狱的问题:
// 所谓的回调地狱就是在回调函数中不断嵌套回调函数
asyncFunc1(opt, function (args1)
asyncFunc2(opt, function (args2)
asyncFunc3(opt, function (args3)
asyncFunc4(opt, function (args4)
// ...
)
)
)
);
Promise的语法格式如下:
var promise = new Promise(function (resolve, reject)
// resolve和reject两个都是函数类型的参数
// 当成功时调用resolve()函数
// 当失败时调用reject()函数
if (/*异步操作成功*/)
resolve([成功参数列表]);
else
reject([失败参数列表]);
);
promise.then(function ([成功参数列表])
// 当执行成功时调用的方法,即resolve
, function ([失败参数列表])
// 当执行失败时调用的方法,即reject
);
案例
获取随机数来打印字符串
使用异步编程实现,如下:
setTimeout(function ()
var random = Math.ceil(Math.random() * 10);
// 如果随机数大于5则直接输出随机数的值;如果随机数小于等于5则循环打印"hello world"
if (random > 5)
console.log("random = " + random);
else
for (var i = 0; i < random; i++)
console.log("hello world");
, 3000);
在一个setTimeout()
函数中又嵌套了另外一个setTimeout()
函数,都是异步操作。如果改成使用Promise来实现,则代码如下:
var promise = new Promise(function (resolve, reject)
setTimeout(function ()
// 获取一位随机数
var random = Math.ceil(Math.random() * 10);
if (random > 5)
// 当随机数大于5时,我们设定为异步操作成功了
// 调用resolve()函数,并且传入一个参数
resolve(random);
else
// 当随机数小于等于5时,我们设定为异步操作失败了
// 调用reject()函数,并且传入一个对象参数
reject(random: random, text: "hello world");
, 100)
);
promise.then(function (random)
// 当异步操作成功时执行的函数,即resolve()
console.log("random = " + random);
, function (obj)
// 当异步操作失败时执行的函数,即reject()
for (var i = 0; i < obj.random; i++)
console.log(obj.text);
);
文件读取
使用fs
模块的readFile()
方法读取文件内容,用回调函数方式实现如下:
var fs = require('fs');
// 文件读取操作readFile()函数是一个异步操作
fs.readFile('./text.txt', function (err, data)
if (err)
// 如果文件读取发生错误,则打印错误对象
console.log(err);
else
// 如果文件读取成功,则打印文件内容
console.log(data.toString())
);
使用Promise进行改写,代码如下:
var fs = require('fs');
// 文件读取操作readFile()函数是一个异步操作
var promise = new Promise(function (resolve, reject)
fs.readFile('./text.txt', function (err, data)
if (err)
// 如果文件读取失败,则调用reject函数
reject(err);
else
// 如果文件读取成功,则调用resolve函数
resolve(data.toString());
);
);
promise.then(function (content)
// 当异步操作成功调用的函数,即resolve
console.log(content.toUpperCase());
, function (err)
// 当异步操作失败调用的函数,即reject
console.log(err)
);
原生Ajax
使用原生Ajax来发送一个GET请求,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<script type="text/javascript">
// 1.创建对象
var xhr = new XMLHttpRequest();
// 2.初始化
xhr.open('GET', 'http://poetry.apiopen.top/sentences ');
// 3.发送
xhr.send();
// 4.处理响应结果
xhr.onreadystatechange = function ()
if (xhr.readyState === 4)
// 判断响应状态码 2xx
if (xhr.status >= 200 && xhr.status < 300)
// 控制台输出响应体
console.log(xhr.response)
else
console.log(xhr.status)
;
</script>
</body>
</html>
使用Promise改写后,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<script type="text/javascript">
var promise = new Promise(function (resolve, reject)
// 1.创建对象
var xhr = new XMLHttpRequest();
// 2.初始化
xhr.open('GET', 'http://poetry.apiopen.top/sentences ');
// 3.发送
xhr.send();
// 4.处理响应结果
xhr.onreadystatechange = function ()
if (xhr.readyState === 4)
// 判断响应状态码 2xx
if (xhr.status >= 200 && xhr.status < 300)
// 当响应成功则调用resolve函数
resolve(xhr.response);
else
// 当响应失败则调用reject函数
reject(xhr.status)
;
);
promise.then(function (response)
// 当异步操作成功后调用的方法,即resolve
console.log(response);
, function (reason)
// 当异步操作失败后调用的方法,即reject
console.log(reason);
);
</script>
</body>
</html>
Promise封装fs模块读取操作
使用Promise封装fs模块读取文件的操作,代码如下:
/**
* 封装一个函数来读取文件内容
* @param path 文件内容
* @returns Promise<any> Promise对象
*/
function readFile(path)
return new Promise(function (resolve, reject)
var fs = require('fs');
fs.readFile(path, function (err, data)
if (!err)
resolve(data.toString());
else
reject(err);
);
);
// 调用函数
readFile('./text.txt')
.then(function (data)
console.log(data);
, function (err)
console.log(err);
);
Promise封装Ajax操作
使用Promise封装Ajax的GET请求,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<script type="text/javascript">
/**
* 封装一个Ajax操作
* @param method 请求方式GET或POST
* @param url 请求路径
* @returns Promise<any> Promise对象
*/
function ajax(method, url)
return new Promise(function (resolve, reject)
// 1.创建对象
var xhr = new XMLHttpRequest();
// 2.初始化
xhr.open(method, url);
// 3.发送
xhr.send();
// 4.处理响应结果
xhr.onreadystatechange = function ()
if (xhr.readyState === 4)
// 判断响应状态码 2xx
if (xhr.status >= 200 && xhr.status < 300)
// 当响应成功则调用resolve函数
resolve(xhr.response);
else
// 当响应失败则调用reject函数
reject(xhr.status)
;
)
// 发送Ajax请求
ajax('GET', 'http://poetry.apiopen.top/sentences')
.then(function (response)
// 当异步操作成功后调用的方法,即resolve
console.log(response);
, function (reason)
// 当异步操作失败后调用的方法,即reject
console.log(reason);
);
</script>
</body>
</html>
Promise的状态
Promise只会发生两种改变:
- pending状态变成resolved状态
- pending状态变成rejected状态
只有这两种,且一个Promise对象只能改变一次,无论变成成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason。注意:value和reason只是形参的名字,可自定义。
promise实例对象中的一个属性state表示Promise的状态,它有三个值:
- pending:表示未决定成功还是失败的状态。
- resolved(或fullfilled):表示成功的状态。
- rejected:表示失败的状态。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<script type="text/javascript">
// pending状态
var promise1 = new Promise(function (resolve, reject)
// 既不调用resolve又不调用reject则是pending状态
);
console.log(promise1);
// resolved(fullfilled)状态
var promise2 = new Promise(function (resolve, reject)
// 调用resolve变成resoled状态
resolve('Success');
);
console.log(promise2);
// rejected状态
var promise3 = new Promise(function (resolve, reject)
// 调用reject变成rejected状态
reject('Error');
);
console.log(promise3);
</script>
</body>
</html>
Promise的基本流程
如何使用Promise?
Promise的API
1、Promise构造函数:Promise(excutor)
- executor是一个函数,表示执行器。即
function(resolve, reject)
。 - resolve是一个回调函数,当在Promise中成功时则调用该函数。
- reject也是一个回调函数,当在Promise中失败时调用该函数。
注:executor会在Promise内部立即同步调用,异步操作在执行器中执行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<script type="text/javascript">
/*
new Promise(excutor); 构造函数,返回一个Promise对象
*/
var promise = new Promise(function (resolve, reject)
// 当成功时调用resolve函数
// 当失败时调用reject函数
);
</script>
</body>
</html>
2、Promise.prototype.then方法:promise.then(onResolved, onRejected)
- onResolved函数,即成功时的回调函数。即
function(value)
。 - onRejected函数,即失败时的回调函数。即
function(reason)
。
注:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的Promise对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<script type="text/javascript">
var promise = new Promise(function (resolve, reject)
// 当成功时调用resolve函数
// 当失败时调用reject函数
);
// 返回一个新的Promise对象
var newPromise = promise.then(function (value)
// 成功的回调函数,即resolve
, function (reason)
// 失败的回调函数,即reject
);
</script>
</body>
</html>
4、Promise.prototype.catch方法:promise.catch(onRejected)
- onRejected函数:失败的回调函数,即
function(reason)
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<script type="text/javascript">
var promise1 = new Promise(function (resolve, reject)
// 修改promise对象的状态
reject('Error');
);
promise1.catch(function (reason)
// catch只有在失败状态时才会调用
console.log(reason);
);
var promise2 = new Promise(function (resolve, reject)
// 修改promise对象的状态。当修改为成功的状态则不会调用catch的回调函数
resolve('Success');
);
promise2.catch(function (reason)
// 因为Promise对象是成功状态,该catch内的回调函数不会被调用
console.log(reason);
)
</script>
</body>
</html>
4、Promise.resolve方法
<!DOCTYPE html>
<html lang="en">
<head<以上是关于Promise学习笔记的主要内容,如果未能解决你的问题,请参考以下文章