1.Promiose 是什么?
Promise是JS中进行异步编程的解决方案。可以有效的避免了之前版本的回调地狱方式。
Promise是一个构造函数。
Promise对象用来封装一个异步操作并可以获取成功或失败的结果值。
简单的看看Promise和传统的回调方式:
/*
编写一个抽奖程序,抽奖的过程是:
取一个随机数1~100,1~30为中奖,31~100为没中奖。
*/
function rand(m, n) {
return Math.ceil(Math.random() * (n - m + 1) + m - 1);
}
console.log('-----------传统方式-----------');
{
function raffle() {
setTimeout(() => {
let a = rand(1, 100);
if (a < 30) {
console.log(`${a} | 恭喜你中奖了, 奖金是10万元。`);
} else {
console.log(`${a} | 很遗憾,您没中奖,再接再厉!`);
}
}, 1000);
}
raffle();
}
console.log('-----------Promise方式-----------');
{
//new Promise的时候需要制定一个回调函数,这个函数的参数是resolve和reject。
//resolve是成功时调用,reject是失败时调用。
const p = new Promise((resolve, reject) => {
setTimeout(() => {
let a = rand(1, 100);
if (a < 30) {
resolve(a);
} else {
reject(a);
}
}, 1000);
});
//then也有2个回调函数,成功第一个,失败第二个。
p.then((value) => {
console.log(`${value} | 恭喜你中奖了, 奖金是10万元。`);
}, (reason) => {
console.log(`${reason} | 很遗憾,您没中奖,再接再厉!`)
});
}
2.什么时候用Promise?
简单的说异步编程的时候会使用Promise。
一般的异步编程有: 1.fs文件读取 2.http请求 3.DataBase操作 4.定时器等等...
下面我们看看简单的读取文件的方法:
const fs = require('fs');
//普通的回调函数的方式
fs.readFile('./test.txt', (err, data) => {
if (err) throw err;
console.log(data.toString());
});
//promise的方式
const p = new Promise(function (resolve, reject) {
fs.readFile('./test.txt', (err, data) => {
if (err) reject(err);
resolve(data);
});
});
p.then(function (value) {
console.log(value.toString());
}, function (reason) {
console.log(reason);
});
这么一看Promise方式的代码好像更复杂....^^;;
我们看看Promise的有点是什么?
3.Promise优点
-
指定回调函数方式更加灵活。
以前必须写在回调函数里面
现在可以启动任务,返回Promise对象,然后给promise对象绑定回调函数。 -
支持链式调用,可以解决回调地狱
以前的回调地狱,现在可以把回调函数放在Promise对象的then方法里面。
第一个有点可能没什么太大的感触,但是回调地狱是没有Promise的链式调用之前是每个开发者的噩梦。
我们举一个简单的例子看看:
const fs = require('fs');
/*
想读取 test1.txt test2.txt test3.txt 三个文件,并且把它们的内容都读取出来。
普通的回调方式,很容易就会发生回调地狱,如果有4个甚至更多文件,这个地狱就更深了...^^;;
*/
//普通读取文件
fs.readFile('./test1.txt', (err, data1) => {
if (err) {
console.log(err);
} else {
fs.readFile('./test2.txt', (err, data2) => {
if (err) {
console.log(err);
} else {
fs.readFile('./test3.txt', (err, data3) => {
if (err) {
console.log(err);
} else {
let result = data1 + '\r\n' + data2 + '\r\n' + data3;
console.log(result);
}
});
}
});
}
});
//使用Promise读取文件, 虽然看着比普通的方式更复杂,
//但是他解决的回调地狱的问题,以及提高了代码可读性。
const p = new Promise(function (resolve, reject) {
fs.readFile('./test1.txt', (err, data) => {
if (err) reject(err);
resolve(data);
});
});
p.then(function (value) {
return new Promise((resolve, reject) => {
fs.readFile('./test2.txt', (err, data) => {
if (err) reject(err);
resolve([value, data]);
});
});
}, function (reason) {
console.log(reason);
}).then(function (value) {
return new Promise((resolve, reject) => {
fs.readFile('./test3.txt', (err, data) => {
if (err) reject(err);
value.push(data);
resolve(value);
});
});
}, function (reason) {
console.log(reason);
}).then((value) => {
console.log(value.join('\r\n'));
});
4.PromiseState
Promise对象的状态有两种:pending和fulfilled。
1.Pending: 等待中
2.Resolved(fulfilled): 成功
3.Rejected: 失败
Pending: 等待中 => Resolved: 成功
Pending: 等待中 => Rejected: 失败
Resolved 方法里 throw 也可以把Promise状态改成 失败
5.PromiseResult
Promise 对象值 Promiseresult
保存异步任务成功或失败的结果值
resovle, reject 两个方法能修改这个值
<!DOCType html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
const p = new Promise((resolve, reject) => { });
console.log(p);
/*
[[Prototype]]: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
*/
const p1 = new Promise((resolve, reject) => {
resolve('OK');
});
console.log(p1); //Promise {<fulfilled>: 'OK'}
/*
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "OK"
*/
const p2 = new Promise((resolve, reject) => {
reject('fail');
});
console.log(p2);
/*
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: "fail"
*/
const p3 = new Promise((resolve, reject) => {
throw ("fail");
});
console.log(p3);
/*
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: "fail"
*/
</script>
</head>
<body>
</body>
</html>
6.Promise API
构造函数 Promise(executor)
(resolve, reject) => {
//这里的函数是同步调用的,不会进队列
}
then(onFulfilled, onRejected) //指定回调,成功的话执行前面的方法,失败执行后面的方法
catch(onRejected) //执行失败时,调用的方法。
finally(onFinally) //无论成功失败,都会执行。
//如果传递参数是非Promise对象,返回结果为成功的的Promise对象,如果是参数是Promise对象,则看Promise本身的状态。
let p1 = Promise.resolve(111);
console.log(p1);
//返回失败的Promise对象,无论是成功的Promise对象也是返回失败的Promise对象。
let p2 = Promise.reject(222);
console.log(p2);
Promise.all
//成功返回成功Promise数组对象,失败返回其中失败Promise对象
const result = Promise.all(p1,p2,p3);
console.log(result);
Promise.race
//谁先改变状态,返回他的Promise结果
//成功返回成功Promise数组对象,失败返回其中失败Promise对象
const result = Promise.all(p1,p2,p3);
console.log(result);
util.promisify
const util = require('util');
const fs = require('fs');
//使用promisify返回一个新的函数
let myReadFile = util.promisify(fs.readFile);
myReadFile('./aa.txt').then(value=>{
console.log(value.toString());
}, reason=>{
console.log(reason);
})
7.附加整理
Promise 调用
let p = new Promise((resolve, reject) => {
setTimeout(()=> {
resolve('OK');
},2000)
})
p.then(value => {
console.log(value);
}, reason => {
console.log(reason);
}).then(value =>{
return new Promise(()=>{});
}).then(value =>{
console.log('111');
}).catch(err =>{
console.warn(err);
});
自定义读取文件方法
function myReadFile(path){
return new Promise((resolve, reject)=>{
require('fs').readFile(path, (err,data)=>{
if(err) reject(err);
resolve(data);
});
})
}
myReadFile('./test.txt')
.then(value=>{
console.log(value.toString());
}, reason=>{
console.log(reason);
})
欢迎大家的意见和交流
email: li_mingxie@163.com
网友评论