Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
再精简到一句话:解决回调地狱问题。
回调地狱就是在一个异步函数中嵌套异步函数…造成代码阅读性很差,不易于后期维护。
新建的Promise就是一个容器,里面可以存放异步操作,也可以存放同步操作
本文以异步读取三个txt文件 1.txt 2.txt 3.txt中的内容并将其合并到一个字符串中为例说明
1.txt 我
2.txt 爱
3.txt 你
const fs = require("fs");
const path = require("path");
let filePath = path.join(__dirname, "files", "3.txt");
// 异步操作可能成功或者失败
// 第一个形参resolve , 成功的时候执行的函数
// 第二个形参reject , 失败的时候执行的函数
let p1 = new Promise((resolve, reject)=>{
//1、同步代码
console.log("同步代码");
// pending(进行中)、fulfilled(已成功)和rejected(已失败)
//2、异步代码
fs.readFile(filePath,"utf-8",(error1, data1)=>{
if(error1){
//失败的时候做的事情
reject(error1); // 调用后面p1.then的第二个函数
}
//读取完之后做的事情
resolve(data1); // 调用后面p1.then的第二个函数
})
});
p1.then((data1)=>{
console.log("读取成功", data1);
},(error1)=>{
console.log("读取失败", error1);
});
// then中传递的参数为两个函数,第一个函数传递resolve的参数,第二个函数传递reject的参数
链式调用的特点:
1、第一个then执行完会执行第二个then
2、then里面的函数的返回值,会被下一个then的形参接收
3、如果返回的是一个promise对象,下一个then的形参是这个promise对象内部调用resolve时候的实际参数
const fs = require("fs");
const path = require("path");
let filePath = path.join(__dirname, "files", "3.txt");
let p1 = new Promise((resolve, reject)=>{
fs.readFile(filePath,"utf-8",(error1, data1)=>{
if(error1){
//失败的时候做的事情
reject(error1)
}
//读取完之后做的事情
resolve("resolve的形参")
})
});
//业内把promise then的写法被称为开火车开发
p1.then((data1)=>{
return p1
},(error1)=>{
console.log("读取失败", error1);
return error1
}).then((data)=>{
console.log(data); // “resolve("resolve的形参")
});
catch用于在then后面捕获异常 finally方法里面的语句无论成功与否都会执行
const fs = require('fs');
const path = require('path');
let filePath1 = path.join(__dirname, "files", "1.txt");
let p1 = new Promise((resolve, reject) => {
fs.readFile(filePath1, "utf-8", (err, data) => {
if(err) {
reject(err);
}
resolve(data);
})
})
p1.then(data => {
console.log("seccess!!!!!!");
console.log(data);
}).catch(err => {
console.log(err);
}).finally(() => {
console.log('我执行了!!!!!');
})
// seccess!!!!!!
// 我
// 我执行了!!!!!
插一条api简单演示
// let readFilePromise = util.promisify(fs.readFile); // 官方给的api,等效于下面的函数
// // function readFilePromise(filePath) {
// // return new Promise((resolve, reject) => {
// // fs.readFile(filePath, "utf-8", (err, data) => {
// // if (err) {
// // reject(err);
// // }
// // resolve(data);
// // })
// // })
// let p1 = readFilePromise(filePath1);
Promise.all([Promise对象1, Promise对象2]).then(data => {
// data是一个数组,按顺序包含Promise对象返回的值
})
const fs = require('fs');
const path = require('path');
const util = require('util');
let filePath1 = path.join(__dirname, "files", "1.txt");
let filePath2 = path.join(__dirname, "files", "2.txt");
let filePath3 = path.join(__dirname, "files", "3.txt");
let writePath = path.join(__dirname, "files", "data.txt");
let readFilePromise = util.promisify(fs.readFile);
let writeFilePromise = util.promisify(fs.writeFile);
let p1 = readFilePromise(filePath1, "utf-8");
let p2 = readFilePromise(filePath2, "utf-8");
let p3 = readFilePromise(filePath3, "utf-8");
Promise.all([p1, p2, p3]).then(data => {
console.log(data);
let str1 = data.join("");
writeFilePromise(writePath,str1, "utf-8");
console.log(data.join(""));
}).catch(err => {
console.log(err);
}).finally(() => {
console.log("999");
})
// [ '我', '爱', '你' ]
// 我爱你
// 999
参数:是一个数组,数组元素是Promise实例对象,只要数组里面的任何一个Promise成功了,则才会执行 then 第一个回调,且只执行1次。
// Promise race()方法
// Promise.race([Promise对象1, Promise对象2]).then(data => {
// // 当数组中Promise对象有一个执行成功, 这里就执行且仅执行一次,data对应执行成功的promise对象
// })
const fs = require("fs")
const path = require("path")
const util = require('util');
let filePath1 = path.join(__dirname, "files", "1.txt")
let filePath2 = path.join(__dirname, "files", "2.txt")
let readFilePromise = util.promisify(fs.readFile);
let p1 = readFilePromise(filePath1,"utf-8")
let p2 = readFilePromise(filePath2,"utf-8")
Promise.race([p1,p2]).then((data)=>{
// p1,p2只要其中一个执行完,就会执行一遍这里的代码,且这里的代码只会执行1次
console.log(123);
console.log(data);
});
//123
//我
入门知识大概就是这些了