一、事件循环
二、AJAX:定义
,总结
//定义request对象
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
// 发送请求:
request.open('GET', '/api/categories');
request.send();
//监听返回状态
request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
}
技巧:异步之后再执行某个函数,则要采用回调函数
缺点:
1.不好维护
2.会形成回调陷阱
三、Promise:定义
,串行
,并行
,总结
1.定义
var promise1 = new Promise(function(resolve, reject) {
//内容略
if(res.statusCode === 200){
resolve(res);//即把AJAX的回调放到外面执行,避免回调陷阱及维护问题
}else{
reject(res);//resolve,reject,all,race是Promise的静态方法
}
});
//对应两种状态,接受及拒绝
promise1.then(res=>{// resolve(res);则这边形参可以接收到这个实参
console.log(value);
});
promise1.catch(res=> {
console.log(value);
});
2.Promise串行
eg:promise1.then().catch().finally().then().then()
3.Promise并行
//注意,并行情况下,[]内不能是状态改变的Promise,应该是请求的,而不是then之后的
all:全都
Promise.all([promise1,promise2,promise3]).then((res)=>{。。。})
成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值
成功时返回的结果数组和原属性数组一致
场景:执行某个,需要其它的都请求回来了数据
race:赛跑
Promise.race([promise1,promise2,promise3]).then((res)=>{。。。})
场景:多个请求,取最新返回的数据
4.总结
Promise对比AJAX相当于在其外面套了个框架
优点:形式上解决了AJAX的缺点问题
四、generator生成器函数:定义
,模拟代码(闭包、field*、next、传参、return)
,应用场景
Es6语法
英 ['dʒenəreɪtə][](javascript:;)* 美 ['dʒɛnəretɚ][](javascript:;)n. 发电机;发生器;生产者
1.相关技术:闭包
闭包:函数的内部函数在函数的外部执行,导致该函数不能释放(内部使用到了的变量)
闭包优势:
1.状态保存在局部的外部函数内,达到私有属性及保存状态的作用
缺点:
1.内存消耗很大
闭包eg:
function A(){
function B(){};
return B;
}
let t=A()();//函数的内部函数在函数的外部执行
2.模拟其原理:实现普通、迭代器委托field*、传参、return
function* Fun2(){
let x0=yield 'Fun2:0;';
let x1=yield 'Fun2:1;'+x0;
}
function* Fun1() {
let a=1;
let y0=yield 'Fun1:0;'+a;
let y1=yield* Fun2();
// return 'this is return'
let y2=yield 'Fun1:2;'+a;
let y3=yield 'Fun1:3;'+y2;
let y4=yield 'Fun1:4;'+y2;
return 'this is return'
}
var x=Fun1();//返回迭代器
console.log(x.next());//测试加变量。{value: "Fun1:0;1", done: false}
console.log(x.next());//测试field*。{value: "Fun2:0;", done: false}
// console.log(x.return('test return'));//测试return。
console.log(x.next('paraToChild'));//测试给内部迭代器传参。{value: "Fun2:1;paraToChild", done: false}
console.log(x.next());//测试加变量。{value: "Fun1:2;1", done: false}
console.log(x.next('para'));//测试自身迭代器传参。{value: "Fun1:3;para", done: false}
console.log(x.next());//测试保存规律。{value: "Fun1:4;para", done: false}
console.log(x.next());//测试迭代完。{value: "this is return", done: true}
console.log(x.next());//测试迭代完。{value: undefined, done: true}
----------------------------------------------------------------
模拟代码:
需求分析:
generator生成器:
1.利用闭包原理//需要定义next为内部函数
2.每一个yield相当于内部函数,即有多个内部函数
3.子项可能也是迭代器,要遍历进去 field*。如果内部迭代器迭代完,换成迭代自身的
4.next传参。是设置上一个yield的返回值。因为每个yield转为内部函数,所以下一个field执行,其实之前field返回值并没有保存
5.return 的实现
----------------------------------------------------------------
function Fun4(){
// 第一部分:每个yield/return转化为内部函数
let x0=()=>{return 'Fun4:0;'};
let x1=()=>{return 'Fun4:1;'+yieldValue[0]};
// 第二部分:状态机
let index=0;//next状态
let done=false;//是否迭代完状态,return可以直接终结迭代器
let yieldValue=[];//传参数组
let returnObj={0:x0,1:x1,length:2};//迭代器对象
// 第三部分:next,return方法(这边写到外面,不至于阅读混乱)
// 第四部分:返回迭代器
return returnObj;
}
function Fun3(){
// 第一部分:每个yield/return转化为内部函数
let a=1;
let y0=()=>{return 'Fun3:0;'+a};
let y1=Fun2();//
// return 'this is return'
let y2=()=>{return 'Fun3:2;'+a};
let y3=()=>{return 'Fun3:3;'+yieldValue[2]};
let y4=()=>{return 'Fun3:4;'+yieldValue[2]};
let y5=()=>{done=true;return 'this is return';}//return 会置done为true
// 第二部分:状态机
let index=0;//next状态
let done=false;//是否迭代完状态,return可以直接终结迭代器
let yieldValue=[];//传参数组
let returnObj={0:y0,1:y1,2:y2,3:y3,4:y4,5:y5,length:6};//迭代器对象
//第三部分:next,return方法(这边写到外面,不至于阅读混乱)
// 第四部分:返回迭代器
return returnObj;
}
----------------------------------------------------------------
next和return的实现:
//next方法
returnObj.next=(arguments)=>{
if(index>(returnObj.length-1) || done) {//超出或done置为true了,则迭代器终结
return {value: undefined, done: true}
}
switch((typeof returnObj[index])){
case 'object':{// 如果其是对象,则遍历进去
let result=returnObj[index].next(arguments);//next传参到内部迭代器
if(result.done){//说明内部已经执行完了,且超出(改为迭代自身)
index+=1;//会自动执行daefault即,迭代自身
}else{
return result;break;
}
}
default:{//否则迭代自身
if(arguments && index>0){
yieldValue[index-1]=arguments;//next传值,保存到上一个field的返回值
}
let result=returnObj[index]();
index+=1;
return {value: result, done: false}
}
}
}
//return方法
returnObj.return=(arguments)=>{//return方法,可以直接终结
done=true;
return {value: arguments, done: done}
}
----------------------------------------------------------------
总结:generator的几个技术点
1.field/ruturn转化为内部函数
2.闭包,状态机
2.返回内部函数的迭代器
3.迭代及内部迭代(next方法,传参)
4.迭代终结:会置done:true
A:next迭代到return:除了会置done:true,和普通next无区别
B:迭代器调用return:传参给自己用(毕竟调用的是return函数而不是next);可以随时终结
C:木有办法终结内部迭代器,除非它自己迭代完了
3.generator生成器 应用场景
1.协程
2.异步操作的同步化表达(要主动在异步的yield表达式,完成位置添加x.next()才会生效)
拿await来说,其是没有等待的功能的
五、async/await:generator的语法糖
Es7语法
awit说白一点:就是在yield表达式,表示完成的位置,主动调用x.next()
所以,看起来就像同步编程一样
async 函数对 Generator 函数的改进,体现在以下三点
1.内置执行器
2.更好的语义
3.更广的适用性
function f11(){
return new Promise((resolve) => {
setTimeout(()=>{
console.log("f11执行")
resolve();
}, 2000);
});
}
function f12(){
return new Promise((resolve,reject) => {
setTimeout(()=>{
console.log("f12执行")
reject();
}, 4000);
});
}
async function Fun5(){
let a=await f11();
let b=await f12().catch(()=>{console.log("f12的catch函数")});
console.log("底下内容")
}
Fun5();
//
f11执行
f12执行
f12的catch函数
底下内容
网友评论