承诺者设计模式
异步----在没有Promise的时候,发送ajax,都是使用回调函数的方式
//jQuery
$.ajax({
url: "./data.json",
method: "get",
success: function (data) {
console.log(data);//请求成功后
},
async: false,
});
$.get("./data.json",function(data){
console.log(data);
})
一般js的处理,谁先回来谁先处理
$.get("./data.json", function (data) {
console.log(data);
});
$.get("./data1.json", function (data) {
console.log(data);
});
但也有特殊情况,数据都返回后,统一处理
ajax并行写法–多个ajax请求都同时发送
并行写法—>数据都返回后,统一处理(Promise会更简单)
//并行写法--->原生JavaScript中的ES5写法
let n = 0;
let mydata = [];
$.get("./data.json", function (data) {
n++;
console.log(data);
mydata.push(data);
if (n >= 3) {
complate(mydata);
}
});
$.get("./data1.json", function (data) {
n++;
console.log(data);
mydata.push(data);
if (n >= 3) {
complate(mydata);
}
});
$.get("./data2.json", function (data) {
n++;
console.log(data);
mydata.push(data);
if (n >= 3) {
complate(mydata);
}
});
function complate(data) {
console.log("111", data);
}
//并行写法---》数据都返回后,统一处理(Promise会更简单)
function fn1() {
return new Promise((resolve, reject) => {
$.get("./data.json", function (data) {
resolve(data);
});
});
}
function fn2() {
return new Promise((resolve, reject) => {
$.get("./data.json", function (data) {
resolve(data);
});
});
}
function fn3() {
return new Promise((resolve, reject) => {
$.get("./data.json", function (data) {
resolve(data);
});
});
}
Promise.all([fn1(), fn2(), fn3()]).then((data) => {
console.log(data);
});
ajax串行写法–多个ajax请求有步骤地执行,必须等第一个ajax请求成功才能发送第二个ajax请求
没有Promise,回调地狱问题,套得太多就会变得很乱。
ajax套ajax,就是回调地狱
//没有Promise,回调地狱问题,套的太多就会变的很乱
//ajax 串行:必须等第一个ajax请求成功才能发送第二个(ajax套ajax--回调地狱)
$.get("./data.json", function (data) {
console.log(data);
$.get("./data1.json", function (data) {
console.log(data);
$.get("./data2.json", function (data) {
console.log(data);
});
});
});
Promise处理串型,代码更加清晰
//Promise处理串型,代码更加清晰
function fn1() {
return new Promise((resolve, reject) => {
$.get("./data.json", function (data) {
resolve(data);
});
});
}
function fn2() {
return new Promise((resolve, reject) => {
$.get("./data.json", function (data) {
resolve(data);
});
});
}
function fn3() {
return new Promise((resolve, reject) => {
$.get("./data.json", function (data) {
resolve(data);
});
});
}
fn1()
.then((value) => {
console.log(value);
return fn2();
})
.then((value) => {
console.log(value);
return fn3();
})
.then((value) => {
console.log(value);
});
仿jQuery完成ajax的异步回调封装
// $.get("./data.json", function (data) {
// console.log(data);
// });
function get(url, callback) {
let xhr = new XMLHttpRequest();
xhr.open("get", url);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let data = JSON.parse(xhr.response);
callback(data);
}
};
xhr.send();
}
get("./data.json", function (data) {
console.log(data);
});
Promise是ES6新增的一个对象(面向对象),它是一个构造函数对象。
let thePromise=new Promise((resolve,reject)=>{
let condition = true
if(condition){
let res = '正确的结果'
resolve(res)
}
if(condition){
let res = '失败的结果'
reject(res)
}
});
console.log(thePromise);
const executor = function executor(resolve,reject){
//resolve,reject都是一个函数,是Promise构造函数中给的形参。
//每个函数调用之后就类似于发了一个誓言,用于修改该Promise实例对象的PromiseState私有属性与PromiseResult私有属性。
//而PromiseState与PromiseResult一旦确定,值就无法修改了。但Promise构造函数的入参函数依旧会执行,所以一般在调用resolve,reject后,使用return中断函数执行,提高代码效率。
let condition = true
if(condition){
let res = '正确的结果'
resolve(res)
}
if(condition){
let res = '失败的结果'
reject(res)
}
}
thePromise=new Promise(executor);//
console.log(thePromise);
Promise必须new,否则报错
let thePromise=Promise((resolve,reject)=>{});//Uncaught TypeError: Promise constructor cannot be invoked without 'new'
Promise必须有一个参数,参数必须是executor执行器函数
let thePromise=new Promise();//Uncaught TypeError: Promise resolver undefined is not a function
使用new调用Promise构造函数之后,会返回一个Promise实例对象。
let thePromise=new Promise((resolve,reject)=>{console.log(1111)});
//1111
console.log(thePromise)//Promise {}
//执行顺序
//1111
//Promise {}//{[[PromiseState]]: "pending",[[PromiseResult]]: undefined,__proto__:Promise.prototype,}
[[PromiseState]]
:表示当前Promise实例对象的状态,默认值为"pending" - 表示等待。[[PromiseResult]]
:表示当前Promise实例对象的结果,默认值为undefined - 表示不存在值。{[[PromiseState]]: "pending",[[PromiseResult]]: undefined,[[Prototype]]:Promise.prototype,}
[[PromiseState]]
与[[PromiseResult]]
并不是可以访问和修改的key名。[[Prototype]]
也不是可以访问和修改的key名,但可以用__proto__
去访问,它的值为构造函数Promise()的原型对象
即Promise.prototype
。承诺者模式的结果只有:成功、失败。
Promise实例对象的executor执行器函数中:
如果执行resolve(参数),PromiseState改为 “fulfilled”,同时 PromiseResult结果改为 成功的结果(参数)。
let thePromise=new Promise((resolve,reject)=>{resolve('成功resolve的返回值')});
console.log(thePromise)//Promise {: '成功resolve的返回值'}
如果执行reject(参数),PromiseState改为 “rejected”,同时 PromiseResult结果改为 失败的结果(参数)。
let thePromise=new Promise((resolve,reject)=>{reject('失败reject的返回值')})
console.log(thePromise)//Promise {: '失败reject的返回值'}
//执行结果:
//Promise {: '失败reject的返回值'}
//后面控制台还会报错:Uncaught (in promise) 失败reject的返回值
如果executor 执行器函函数报错,PromiseState改为 “rejected”,同时 PromiseResult结果改为 报错的原因。
let thePromise=new Promise((resolve,reject)=>{console.log(不存在的会导致报错的变量)})
console.log(thePromise)//Promise {: 报错原因对象}
//执行结果:
//Promise {: 报错原因对象}
//后面控制台还会报错:ReferenceError: 不存在的会导致报错的变量 is not defined
[[PromiseState]]
(状态)有三种结果:
当前Promise实例对象
处于等待
的状态
。当前Promise实例对象
处于成功
的状态
。当前Promise实例对象
处于失败
的状态
。当前Promise实例对象
的状态
一旦确定为("fulfilled"成功或"rejected"失败),将无法修改
let thePromise = new Promise((resolve, reject) => {
console.log(0);
resolve("resolve的返回值1");
console.log(1);
resolve("resolve的返回值2");
console.log(2);
reject("reject的返回值");
console.log(3);
});
console.log(thePromise);//Promise {: 'resolve的返回值1'}
//执行结果:
//0
//1
//2
//3
//Promise {: 'resolve的返回值1'}
通过p.__prtot__
—>Promise.prototype
—>Object.prototype
得到公有属性
thePromise.then(onfulfilled,onrejected)
两个参数
[[PromiseResult]]
结果[[PromiseResult]]
结果函数参数如何执行: 根据Promise实例对象的[[PromiseState]]
属性
pending 状态: 两个函数都不会执行,都是等待
new Promise((resolve, reject) => {
setTimeout(() => {}, 1000);
}).then(
(value) => {
console.log("onfulfilled函数", value);
},
(err) => {
console.log("onrejected函数", err);
}
);
//永不执行.then()里的任意一个入参函数。
fulfilled 状态: 执行 onfulfilled函数,参数为Promise实例对象的[[PromiseResult]]
结果
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000);
}).then(
(value) => {
//1000毫秒后输出
console.log("onfulfilled函数", value);
},
(err) => {
console.log("onrejected函数", err);
}
);
rejected 状态: 执行 onrejected函数,参数为Promise实例对象[[PromiseResult]]
结果
new Promise((resolve, reject) => {
setTimeout(() => {
reject(100);
}, 1000);
}).then(
(value) => {
console.log("onfulfilled函数", value);
},
(err) => {
//1000毫秒后输出
console.log("onrejected函数", err);
}
);
同一个实例可以调用多次.then(),不会相互影响,每次都执行
console.log("thePromise 定义前");
let thePromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000);
console.log("new Promise里");
});
console.log("thePromise.then()前");
thePromise.then(
(value) => {
//1000毫秒后输出
console.log("onfulfilled函数", value);
},
(err) => {
console.log("onrejected函数", err);
}
);
console.log("thePromise.then()后");
thePromise.then((value) => {
console.log("第二个onfulfilled函数", value);
});
thePromise.then((value) => {
console.log("第三个onfulfilled函数", value);
});
console.log(thePromise);
Promise实例对象.then()执行完之后,返回的结果仍然是一个Promise实例对象。
假设:thePromise1
是一个Promise实例对象
,thePromise2=thePromise1.then()
,thePromise3
是thePromise1.then()里的函数返回的Promise实例对象
。
thePromise1.then()
里面的回调函数都没执行,如thePromise1
是pending状态
。则thePromise2
也是pending状态
,值为undefined
。thePromise1.then()
执行了onfulfilled函数
/onrejected函数
,thePromise2
要看该thePromise1.then()里被调用函数的返回值
如果没有返回值(undefined)。则thePromise2
状态就是fulfilled
,值为undefiend
。
如果有返回值,看返回值的类型:
thePromise2
状态就是fulfilled
,值为返回值
。Promise实例对象
(thePromise3)。则thePromise2
状态和值就是Promise实例对象
(thePromise3)决定。
返回的值是一个新的Promise实例对象
,只是该Promise实例对象的状态与值
和返回的那个Promise的实例(thePromise3)的状态与值
一样。
注意:返回的新的Promise实例对象
不能是调用.then()的Promise实例对象本身
,即不能是thePromise1
。
let thePromise1=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(300)
resolve(300)
},1000)
});
let thePromise3=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(400)
resolve(444)
},6000)
});
let thePromise2=thePromise1.then(res=>{
console.log("222",res);
return thePromise3
})
console.log(thePromise1,thePromise2,thePromise3)
console.log(thePromise1===thePromise2,thePromise1===thePromise3,thePromise2===thePromise3)//false false false
该thePromise1.then()里被调用函数
被调用过程中出现错误。则thePromise2
状态就是"rejected",值为失败原因对应的错误对象
。
.then()链
执行过程中出错,不会中断.then()链
,但是.then()中被调用函数的下面语句
不再执行。
let pp=new Promise((resolve,reject)=>{
resolve(200)
});
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(100)
},1000)
});
p.then(value=>{
console.log(value)//100
return value/2
},reason=>{
console.log(reason)
}).then(value=>{
console.log(value)//50
return a//错误
},reason=>{
console.log(reason)
}).then(value=>{
console.log(value)
return "hello";
},reason=>{
console.log(reason)//报错原因 a is not defined
return pp;//成功 200
}).then(value=>{
console.log(b);//报错
console.log(value);//并不会打印value了。
},reason=>{
console.log(reason)
}).then(value=>{
console.log(value)
},reason=>{
console.log(reason);//报错原因 b is not defined
})
为了保持then()链,连接下去,上一个then()没有参数,交给下一个then()处理。
let thePromise1=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(300)
resolve(300)
},1000)
});
thePromise1.then().then(value=>{
console.log("111",value)
},reason=>{
console.log("222",reason)
})
//300
//111 300
let thePromise1=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(300)
reject(300)
},1000)
});
thePromise1.then().then(value=>{
console.log("111",value)
},reason=>{
console.log("222",reason)
})
//300
//222 300
thePromise.then()里可以只写onfulfilled或onrejected,也可以都不写。
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(300)
},1000)
});
p.then(null,reason=>{
console.log("222",reason);
})
p.then(res=>{
console.log("222",res);
})
p.then()
catch() 代替.then()第二个参数
new Promise((resolve, reject) => {
setTimeout(() => {
reject(300);
}, 1000);
})
.catch((err) => {
console.log(333,err);
})
//333 300
//相当于:
new Promise((resolve, reject) => {
setTimeout(() => {
reject(300);
}, 1000);
}).then(null,(err) => {
console.log(333,err);
})
//333 300
thePromise.then()链传透
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(300);
}, 1000);
})
.then((value) => {
console.log(111,value); //300
})
.then((value) => {
console.log(222,value); //undefined
return a;
})
.then((value) => {
console.log(value);
})
.then((value) => {
console.log(value);
})
.then((value) => {
console.log(value);
})
.catch((err) => {
//a is not defined
console.log(333,[err]); //err
})
//111 300
//222 undefined
//333 [ReferenceError{message: "a is not defined"}]
finally() 不论上一步的结果如何,都必须执行。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(300);
}, 1000);
})
.then((value) => {
console.log(111,value); //300
})
.then((value) => {
console.log(222,value); //undefined
return a;
})
.then((value) => {
console.log(value);
})
.then((value) => {
console.log(value);
})
.then((value) => {
console.log(value);
})
.catch((err) => {
//a is not defined
console.log(333,[err]); //err
})
.finally((val) => {
console.log(444,"111"); //必须执行
});
//111 300
//222 undefined
//333 [ReferenceError{message: "a is not defined"}]
//444 '111'
try {
console.log(a);
} catch (err) {
console.log(err, "111");
} finally {
//可有可无,有 一定会执行
console.log("aaa");
}
try {
console.log("nnn");
console.log(a); //立刻中断,走catch
console.log("mmm");
} catch (err) {
//如果try里面没错,永远不会执行catch
console.log(err, "111");
}
console.log("222");
try块代码优先执行,try块代码一定会有。
catch块代码在try块代码出错时再执行,catch块代码一定会有。
finally块代码可有可无,如果有,那么一定会执行。
就算在try块或catch块中已经return,也一定会执行这里面的代码。
如果不放在finally块中,而是在finally块外面,那么当try块或catch块有return并执行到,会直接退出当前函数作用域,而不再执行后面代码。
(() => {
try {
throw new Error("error");
} catch (e) {
console.log(e.message);
return;
} finally {
console.log("finally");
}
console.log("done");
//error
//finally
})();
(() => {
try {
throw new Error("error");
} catch (e) {
console.log(e.message);
return;
}
console.log("finally");
console.log("done");
//error
})();