Promise基本介绍
什么是Promise?
所谓Promise,简单说就是一个容器,里面保存着通常是一个异步操作的结果。
什么是异步操作
js语言是单线程机制。单线程就是按次序执行,执行完一个任务再执行下一个。但是不影响异步还是同步 异步就是从主线程发射子线程完成任务 前一个任务结束后执行回调函数 后一个任务不等前一个任务执行 所以程序执行顺序和任务顺序排列的顺序是不一致的 所以称为异步任务
回调函数
一个函数(A)作为实参传入到另一个函数(B)当中 并且函数B在内部调用了 则称为回调函数
setTimeout(()=>{
console.log("hello");
},1000)
console.log("666")
此时作为函数A console.log(“hello”);传入到定时器B中 称为回调函数
此时setTimeout会在子线程等待一秒 然后执行 但是它不会堵塞主线程
什么是回调地狱
$.ajax({
url: '我是第一个请求',
type: 'get',
success(res) {
// 现在发送第二个请求
$.ajax({
url: '我是第二个请求',
type: 'post',
data: { a: res.a, b: res.b },
success(res1) {
// 进行第三个请求
$.ajax({
url: '我是第三个请求',
type: 'post',
data: { a: res1.a, b: res1.b },
success(res2) {
console.log(res2)
}
})
}
})
}
})
对于以上代码 是一层一层向下嵌套的 不便于维护 且如果中间有些地方出错之后就会导致后面的无法进行
所以为了解决回调地狱的问题 Promise就出场了
Promise解决回调地狱的原理
Promise特点
Promise对象其实是构造函数 构造函数接受了function(resolve,rejected)作为参数 此时该函数就是Promise构造函数的回调函数 生成Promise实例resolve和reject
1 promise对象有三个状态 pending(进行中) fulfilled(已成功) rejected(已失败) 只有异步操作的结果可以改变promise的状态
2 一旦状态改变 从pending变到fulfilled pending变成rejected 则状态就凝固了
promise对象其实是构造函数 构造函数接受了function(resolve,rejected)作为参数 此时该函数就是promise构造函数的回调函数 生成promise实例resolve和rejected
另外
1promise在创建实例就会执行
● new Promise时传入的函数是同步执行的。在这个函数内部调用resolve或reject只是告诉Promise对象任务已经完成,但不会立即执行then方法绑定的回调。
let p=new Promise(function(resolve,reject){
console.log("6");
resolve();
})
p.then(function(){
console.log("9");
})
console.log("2");
因为立即执行 所以输出结果为6 9 2
调用reslove和rejecte并不会影响Promise函数的执行
new Promise((resolve, reject) => {
resolve(1);
// return resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
正常输出结果为 2 1
加上return resolve(1)后,Promise对象会立刻resolved,then回调会同步执行 所以此时2不会输出 而是直接执行回调函数
resolve函数目的是将promise的状态变为成功 在异步操作成功时候将参数传递出去 reject函数是将promise状态变成失败 在失败时候调用
Promise常用方法
then()和catch()
new Promise(function(resolve,reject){
//resolve(1);
reject(1)
})
.then(function(res){
console.log("成功",res);
},function(err){
console.log("失败",err);
})
new Promise((resolve,reject)=>{
resolve(1)
}).then(()=>{
throw new Error;
}).catch((err)=>{
console.log(err);
})
then方法有两个参数 一个当Promise对象成功时候作为回调函数调用 一个作为Promise对象失败时候调用
而catch相当于then方法的特例 只在失败时候调用 因为Promise对象失败具有冒泡的性质 所以会被最外层的catch捕获到错误
finally()
finally()方法用于指定不管Promise 对象最后的状态 如何,都会执行的操作。
finally 方法的回调函数不接受任何参数,所以finally方法里面的操作和promise 返回的状态无关,不依赖于promise的执行结果
server.listen(port)
.then(function () {
// ...
})
.finally(server.stop);
all()
romise.all() 方法用于将多个Promise 实例,包装成一个新的实例
接受一个数组作为参数 有以下几种情况
1 数组里面的promise实例都是fulfilled,新的实例状态才是fulfilled
2 实例对象只要有一个是rejected,p的状态就是rejected
const p1=new Promise((resolve,reject)=>{
resolve("hello")
})
.then(result=>result)
.catch(e=>e)
const p2=new Promise((resolve,reject)=>{
throw new Error("报错了")
})
.then(result=>result)
.catch(e=>e)
Promise.all([p1,p2])
.then(result=>console.log(result))
.catch(e=>console.log(e))
race()
因为Race有赛跑的意思 Promise.race方法用于处理多个Promise对象,只要有一个Promise对象执行成功或失败,race方法返回Promise对象就会兑现。
let fun1=new Promise((reslove,reject)=>{
setTimeout(()=>{
let data1='哈哈'
reslove(data1);
},400)
})
let fun2=new Promise((reslove,reject)=>{
setTimeout(()=>{
let data2='哈哈哈'
reslove(data2);
},500)
})
Promise.race([fun1,fun2])
.then((res)=>{
console.log(res);
})
.catch((err)=>{
console.log(err);
})
reslove()
reslove()可以使其传递的参数变为Promise对象
参数有一下几种情况
1 Promise.reslove接受的参数是有then方法的 转成Promise对象之后直接调用对象里面的.then方法
2 参数是个Promise对象 不做任何改动
3参数不是对象 会返回一个新的Priomise对象 且状态是resloved
4没有参数 直接返回一个resloved的Promise对象
let thentable={
then:function(reslove,reject){
reslove(42)
}
}
let p1=Promise.resolve(thentable);
p1.then(function(value){
console.log(value);
})
const p = Promise.resolve('Hello');
p.then(function (s) {
console.log(s)
});
const p2 = Promise.resolve();
p.then(function () {
// ...
});
Promise应用
封装ajax
function sendAjaxRequest(url, method, params) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(method, url);
//封装请求的metho和地址
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function () {
//判断返回码的状态
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject(new Error(xhr.statusText));
}
}
};
//处理发送请求失败
xhr.onerror = function () {
reject(new Error('ajax发送请求失败'));
};
if (method === 'POST') {
xhr.send(JSON.stringify(params));
} else {
xhr.send();
}
});
}
// 使用示例
sendAjaxRequest('http://localhost:5000/get/get', 'GET')
.then(function (res) {
console.log(res);
})
.then(function (res) {
let sendData = { name: 'John', age: 25 };
return sendAjaxRequest(`http://localhost:5000/get/sendReq?sendData=${sendData}`, 'GET');
})
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.log(err);
});
封装axios
function sendAjaxRequest(url, method, params) {
return new Promise(function(resolve, reject) {
axios({
method: method,
url: url,
data: params
})
.then(function(response) {
resolve(response.data);
})
.catch(function(error) {
reject(error);
});
});
}
// 使用示例
sendAjaxRequest('http://localhost:5000/get/get', 'GET')
.then(function(res) {
console.log(res);
})
.then(function() {
let sendData = { name: 'John', age: 25 };
return sendAjaxRequest("http://localhost:5000/get/sendReqPOST", 'POST', sendData);
})
.then(function(res) {
console.log(res);
})
.catch(function(err) {
console.log(err);
});
判断图片状态
const preloadImage = function (path) {
return new Promise(function (resolve, reject) {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
总结
Promise可以解决回调地狱 在交互中采用异步操作可以避免堵塞线程 对错误进行捕获 便于维护
下周主要还是写项目进行交互 然后就是可以整理一下原生js写的播放器 写的有点乱其实