ES6基础5(Promise)-学习笔记
Promise
- 为什么需要?
- 依次加载3个请求 index.txt–>name.txt–>age.txt
- 使用fs代替http
- promise 解决无限嵌套
三个状态
- pending 等待状态
- fulfilled 成功状态
- rejected 失败状态
状态转换
- 开始状态pending,resolve()可转变为成功状态,reject变为失败状态
- 一旦状态改变则不可改变
- resolve(xxx)数据会转给then(成功,失败)成功回调方法
- reject(yyy)数据会转给then中失败回调方法
- 是成功态就调成功回调 失败态相同
- 需要把then中的成功、失败回调保存
手写Promise源码
const SUCCESS = "fulfilled"
const FAILURE = "rejected"
const PENDING = "pending"
function resolvePromise(value,resolve,reject){
if(typeof value === 'function' || typeof value === 'object'){
try{
let then = value.then;
if(typeof then === 'function'){
then.call(value,x=>{
//resolve(x)
resolvePromise(x) //递归解析(如果参数也是Promise)
},err=>{
reject(err)
})
}else{
resolve(value)
}
}catch(e){
reject(e)
}
}else{
resolve(value); //返回普通值
}
}
class Promise{
constructor(executor){
this.status = PENDING; //初始状态
this.value = undefined; //保存成功态数据
this.reason = undefined; //保存失败态数据
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if(this.status = PENDING){ //在等待态时才可修改
this.status = SUCCESS;
this.value = value;
this.onFulfilledCallbacks.forEach(fn=>fn())
}
}
let reject = reason => {
if(this.status = PENDING){
this.status = FAILURE;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn=>fn())
}
}
try{
executor(resolve,reject);
}catch(e){
reject(e)
}
}
then(onFulfilled,onRejected){ //成功回调 失败回调
let p = new Promise((resolve,reject)=>{
//console.log(onFulfilled,onRejected)
if(this.status = SUCCESS){
let v = onFulfilled(this.value)
resolvePromise(v,resolve,reject)
}
if(this.status = FAILURE){
let v = onRejected(this.reason)
resolvePromise(v,resolve,reject)
}
if(this.status = PENDING){
this.onFulfilledCallbacks.push(() => {
let v = onFulfilled(this.value)
resolvePromise(v,resolve,reject)
})
this.onRejectedCallbacks.push(() => {
let v = onRejected(this.reason)
resolvePromise(v,resolve,reject)
})
}
})
return p;
}
}
module.exports = Promise
同步异步概念
//回调陷阱
$.ajax({
type:'get',
url:'A',
success:function(A){
$.ajax({
type:'get',
url:'B/'+A,
success:function(B){
$.ajax({
type:'get',
url:'B/'+A,
success:function(B){
$.ajax({
type:'get',
url:'B/'+A,
success:function(B){
}
})
}
})
}
})
}
});
//promise 写法
var p = new Promise(function(resolve,reject){
//resolve 成功后
//reject 失败后
if(true){
resolve("成功")
}else {
reject("失败")
}
});
p.then(function(resolved){
//成功后
},function(rejected){
//失败后
});
//解决回调问题
//链式写法
var p = new Promise(function(resolve,reject){
if(true){
resolve("成功")
}else {
reject("失败")
}
});
p.then(function(resolved){
console.log(resolved) // 成功
//成功后
return new Promise(function(resolve,reject){
if(false){
resolve("成功123")
}else {
reject("失败123")
}
})
},function(rejected){
//失败后
}).then(function(resolved){
//成功后
console.log(resolved) // 成功123
},function(rejected){
//失败后
console.log(rejected) //"失败123"
});
原始http请求:
var xmlhttp = getXMLHttpRequest();
xmlhttp.open("get","http://localhost:3333/info",true);
xmlhttp.send();
//xmlhttp.setRequestHeader("Content-Type", "application/json");
//xmlhttp.send(JSON.stringify({"name":"John", "age":"24"}));
xmlhttp.onreadystatechange= function() {
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(xmlhttp.responseText);
}
};
http请求封装(promise):
//发送请求 url 接口地址 请求类型 type 传的数据data
const getJSON = function(url,type, data) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
};
if (this.status === 200) {
resolve(this.response); //成功后
} else {
reject(new Error(this.statusText)); //失败了
}
};
const client = new XMLHttpRequest();
client.open(type, url);
client.onreadystatechange = handler;
client.responseType = "json";
if(type =='get'){
client.send();
}else {
client.setRequestHeader("Content-Type", "application/json");
client.send(JSON.stringify(data));
}
});
return promise;
};
调用请求:
//发送请求
let getData = ()=>{
getJSON('http://localhost:3333/get_table','get')
.then(res=>{
//成功后
console.log(res);
},function(error){
//失败后
});
}
jquery中
//jquery 高于1.5 defrred对象基于promise
//then() done() //
$.ajax({
type:'get',
url:this.url+"/get_table",
dataType:'json'
}).done(res=>{ //不支持延续任务的调用
if(res.code=='200'){
var data = JSON.parse(res.result);
this.listShow(data);
}
}).fail(function(){
});
串行并行
串行:
queryThen(){ //串行
// getJSON(this.url+"/get1","get")
// .then(res=>{
// console.log(res);
// return getJSON(this.url+"/get2","get",res.result.id)
// },err=>{
// console.log(err)
// }).then(res=>{
// console.log(res);
// }).catch(err=>{
// console.log(err)
// });
//jq的写法
// $.ajax({
// type:'get',
// url:this.url+"/get1",
// dataType:'json'
// }).then(res=>{
// return $.get(this.url+"/get2");
// },err=>{
// }).then(res=>{
// },err=>{
// })
//async的写法
var _this = this;
async function f(){
var d1 = await getJSON(_this.url+"/get1","get");
var d2 = await getJSON(_this.url+"/get2","get",d1.result.id);
//_this.listShow(d2);
console.log(d2); //{code:"200",msg:"get2"}
};
f();
},
并行:
queryWhen(){ //并行
$.when(
$.get(this.url+"/get1"),
$.get(this.url+"/get2")
).then((d1,d2)=>{
console.log(d1,d2);
},err=>{
});
//原生
// var p1 = new Promise((resolve,reject)=>{
// getJSON(this.url+"/get1","get")
// .then(res=>{
// console.log(res);
// }).catch(err=>{
// console.log(err)
// })
// });
// Promise.all([
// p1,
// getJSON(this.url+"/get2","get")
// .then(res=>{
// console.log(res);
// }).catch(err=>{
// console.log(err)
// })
// ])
// .then(([d1,d2])=>{
// console.log(d1,d2);
// },err=>{
// });
//Promise.race() //返回的是请求快的,不管结果是成功或失败
// var p3 = new Promise((resolve,reject)=>{
// setTimeout(()=>{
// resolve('1111')
// },1000)
// });
// var p4 = new Promise((resolve,reject)=>{
// setTimeout(()=>{
// resolve('22222')
// },2000)
// });
// Promise.race([p3,p4])
// .then((d)=>{
// console.log(d);
// },err=>{
// });
}
async-await
//async的用法 作为一个关键字放在函数前面
//具体的写法
async function f(){ //表示函数是一个异步函数
return 'abc'
};
f(); //没有执行abc
console.log('xyz')
//第二种方式
async function f(){ //async函数返回一个promise,默认是成功状态,并把函数的返回值传给then的第一个参数
return 'abc'
};
console.log(f()); //promise
console.log('xyz')
//调用
async function f(){ //async函数返回一个promise,默认是成功状态,并把函数的返回值传给then的第一个参数
return 'abc'
};
f().then(res=>{
console.log(res)
});
console.log('xyz');
await-异步同步化
//await
console.log(1);
async function f(){ //表示函数是一个异步函数
console.log(2);
await 100; //阻塞
console.log(3); //异步任务
};
f();
console.log('xyz')
//1 2 xyz 3
function p(){
return new Promise(resolve=>{
setTimeout(()=>{
resolve();
console.log('abc')
},1000)
})
};
async function f(){ //表示函数是一个异步函数
console.log(2);
await p(); //阻塞
console.log(3); //异步任务
};
f(); //见下图片
微任务 宏任务
//宏任务和微任务
setTimeout(()=>{ //宏任务
console.log(1)
},0)
new Promise(function(resolve,reject){ //微任务
resolve();
console.log(2);
}).then(function(){
console.log(3)
})
//231
setTimeout(()=>{ //宏任务
console.log(1)
},0)
new Promise(function(resolve,reject){ //微任务
resolve();
console.log(2);
}).then(function(){
console.log(3)
});
console.log(4)