1.promise的基本使用
概述:
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果;
1. Promise 构造函数: Promise (excutor) {};
2. Promise.prototype.then 方法;
3. Promise.prototype.catch 方法;
基本语法:
// 实例化 Promise对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// let data = "数据库中的用户数据";
// resolve(data);
let err = "数据读取失败";
reject(err);
}, 1000)
});
// 调用promise对象的then方法
p.then((value) => {
console.log(value);
}, (reason) => {
console.error(reason);
})
上述代码注释部分可以自行打开进行测试。
此处补充:对象总共有三个状态:初始化,成功,失败
在promise进行实例化时接受一个参数,参数为一个函数类型的值,该函数有两个形参,一个resolve,一个reject(可以对这两个形参任意命名,但是潜规则为resolve与reject),在函数内部封装两个异步的操作,我们在函数内部可以调用resolve与reject。
当我们调用的为resolve,promise对象的状态变为成功,当成功之后我们可以调用对象中的then方法,then方法接受两个参数,并且两个参数都是函数类型的值。每个函数都有一个形参,成功的形参为value,失败的为reason。只要上面调的是resolve那么then执行的就一定是第一个回调函数的方法。
当我们调用的是reject,promise对象的状态就会变为失败,这个时候调用then方法中的第二个回调函数。
通过上述方式我们就把异步任务封装在一个promise对象当中。
2.promise读取文件
// 1.引入fs模块
const fs = require('fs');
// 2.调用方法读取文件
/* fs.readFile("./resoources/为学.md", (err, data) => {
// 如果失败则抛出错误
if (err) throw err;
// 如果没有出错则输出内容
console.log(data.toString());
}) */
// 3.使用promise封装
const p = new Promise((resolve, reject) => {
fs.readFile("./resoources/为学.md", (err, data) => {
// 如果失败调用reject,改变p的状态为失败
if (err) reject(err);
// 如果没有出错改变p的状态为成功,传入的参数为成功的值
resolve(data);
})
});
p.then((value) => {
console.log(value.toString());
}, (reason) => {
console.log("读取失败");
})
上述代码需要安装node.js,可在vscode终端运行调试
3.promise封装ajax请求
// 请求地址:https://api.apiopen.top/getJoke
const p = new Promise(function(resolve,reason){
// 原生请求
// 1、创建对象
const xhr = new XMLHttpRequest();
// 2、初始化
xhr.open("GET","https://api.apiopen.top/getJoke");
// 3、发送
xhr.send();
// 4、绑定事件,处理响应结果
xhr.onreadystatechange = function(){
// 判断状态
if(xhr.readyState == 4){
// 判断响应状态码 200-299
if(xhr.status>=200 && xhr.status<=299){
// 成功
resolve(xhr.response);
}else{
// 失败
reason(xhr.status);
}
}
}
});
运行结果:
Promise.prototype.then:
代码实现及相关说明:
p.then(function(value){
console.log(value.toString());
},function(reason){
console.log(reason); // 读取失败
})
4.promise.prototype.then方法
// 1.创建promise对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("用户数据");
// reject("出错啦");
}, 1000)
});
// 调用then方法 then方法的返回结果是promise对象,对象状态由回调函数的执行结果决定
// 1.如果回调函数中返回的结果是 非promise类型的属性,状态则为成功,返回值为对象的成功的值
const result = p.then(value => {
console.log(value);
// 1.非promise类型的属性
// return 111
// 2.是promise对象
// return new Promise((resolve, reject) => {
// // resolve("ok");
// reject("error");
// });
// 3.抛出错误
throw "出错啦!"
}, reason => {
console.warn(reason);
});
console.log(result);
then的返回结果是promise对象,该对象的状态由回调函数(创建的promise对象中的resolve与reject)的执行结果决定的
1.如果回调函数中返回的结果是 非promise类型的属性(上面的return 111),状态则为成功,返回值为对象的成功的值。
2.如果回调函数中返回的结果是 promise类型的属性(上面的return new promise ()),我内部返回的promise的状态就决定了我then方法返回的promise状态
3.抛出错误的状态也是一个失败的promise。
then方法是可以链式调用的,其中reason是可以省略的。
// 链式调用
p.then(value =>{
}).then(value =>{
})
5.promise实践练习
// 引入fs模块
const fs = require("fs");
// 使用promise实现
const p = new Promise((resolve, reject) => {
fs.readFile('./resources/为学.md', (err, data) => {
resolve(data.toString());
});
});
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
resolve([value, data]);
})
})
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
// 压入;
value.push(data);
resolve(value);
})
})
}).then(value => {
console.log(value.join('\r\n'));
})
6.promise对象的catch方法
用于指定promise失败的一个对象的回调,类似于语法糖,then的第一个成功的函数不调用。
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 设置p对象的状态为失败,并设置失败的值
reject("出错啦!")
}, 1000)
});
p.catch(function (reason) {
console.warn(reason);
})