/*P106-异步-setTimeout*/
//JS的代码一般情况下是同步执行的,按正常顺序一步一步执行,
//缺点就是,遇到需要花费时间才能完成的代码,他会持续等待,完成之后,才会继续往下执行
//异步就是把花费时间太长的代码放到另一个地方去执行,剩下的代码继续执行
//异步的代码会执行完毕之后,把结果返回到同步执行的代码中来
//常见的异步的例子,使用fetch进行ajax远程加载数据,setTimeOut,还有自定义的promise等
/*setTimeOut计时器
//两个参数:第一个是计时完成之后调用的回调函数,第二个参数是推迟多久
//JS是单线程语言,它的异步操作使用event loop的机制来控制的,同学可以自己研究一下
console.log('第一行代码');
setTimeout(()=>{
console.log('1秒后执行,打印结果在第三');
},1000);
console.log('第二行代码')
//output
// index.js:11 第一行代码
// index.js:15 第二行代码
// index.js:13 1秒后执行,打印结果在第三
//end
/** */
/*取消定时器
//定义定时器的时候,把它赋值给一个变量,然后在需要取消定时器的地方使用clear
console.log('第一行代码');
var timer1 = setTimeout(()=>{
console.log('1秒后执行,打印结果在第三');
},1000);
console.log('第二行代码')
setTimeout(()=>{
clearTimeout(timer1);
console.log('中断了timer1的执行');
},500);
//output:
// 第一行代码
// index.js:31 第二行代码
// index.js:35 中断了timer1的执行
//end
/** */
/*P107-异步-setInterval*/
//和setTimeout类似,是每隔一段时间执行一次回调函数
/*setInterval
setInterval(()=>{
let date = new Date();
console.log(`${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`)
},1000);
//output:
// index.js:51 17:35:27
// index.js:51 17:35:28
// index.js:51 17:35:29
// index.js:51 17:35:30
// ......//可以一直执行下去
//end
/** */
/*setInterval的取消
var interval = setInterval(()=>{
let date = new Date();
console.log(`${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`)
},1000);
setTimeout(()=>{
clearInterval(interval);
},5000);
//outputs:执行5次之后就停止了
// index.js:66 17:39:43
// index.js:66 17:39:44
// index.js:66 17:39:45
// index.js:66 17:39:46
// index.js:66 17:39:47
//end
/** */
/*P108-异步-创建Promise
//Promise可以让我们创建自定义的异步操作
//把一些耗时的工作交给promise,其他同步代码可以继续执行
//以下为老师讲解文本,详细研究之用
//使用new关键字创建新的Promise对象,构造函数Promise()中使用回调函数A作为参数
//回调函数A又接收2个参数,resolve函数和reject函数,【老师这里叫函数】
//resolve是在promise执行完毕之后,调用resolve返回执行的结果
//接收resolve参数,传递的是一个回调函数,这样,我在里面模拟一下一个比较耗时的操作,我用setTimeout
//传递一个回调函数进来,时间设置2000毫秒,2秒后,执行{}中写的resolve(),
//resolve()接收一个参数,是执行成功之后返回的结果。比如说,这里返回一个字符串‘执行成功’,这样就创建了一个promise
var promise = new Promise(resovle=>{
setTimeout(()=>{
resovle('执行成功(promise内部语句)');
},2000);
});
/** */
/*以下是我的个人思考,不是老师的讲解
//VH:我能理解,主函数定义的时候,回调函数作为参数没有(),我们
//老师说new Promise(resolve=>{})这个resolve是函数
//我见过的回调函数,是主函数参数没有括号,回调函数转换成箭头函数的时候,保留参数,没有函数名。这个参数是常见的普通变量。
//如果我所见的主函数也是个回调函数的话,如何写呢?因为它的参数没有括号,改写成箭头函数的时候,就是参数=>{},这个时候,参数就是一个函数。
//这时候,也把它箭头化,没有自己的名字,只有参数名字,直接参数=>{参数(里面又是箭头函数);},但是resolve=>{resolve('文字')},这不就是类似request(result=>{console.log(result)})直接调用嘛。
//定义的时候,回调函数也是把函数名留下,函数体内函数名(),这个是什么方法?对比,那个参数只是普通变量来说都改写,是不是?我原来以为参数
//不是说异步的参数才是回调,而是说异步可以用回调函数。也可以不用回调。同步代码也可以回调。
//我的疑问就是解决了,宿主函数定义的时候,就已经是回调结构了。箭头函数的作用,就是不用写定义回调函数的正式。省掉function和函数名。其他不变。
//那么宿主函数也变成了回调怎么办?改写成箭头函数,就是去掉function和函数名,变成参数=>{参数()的样子},那么我带着自己的回调函数的时候,怎么改写箭头呢?
request(result=>{result});
去掉定义时的function和函数名,
Promise(cd=>{cd()}),如果再带回调呢?见过一个说是回调地狱的东西,是不是和我这个找到东西类似呢?
test(cd=>{cd(这里应该怎么写?)}),
也许
function test(canshu){
canshu();
}
function request(cd){
cd();
}
function callback(result){
console.log(result);
}
前两个都是回调函数,最后一个不是回调函数。
嵌套
后两个可以
request(result=>{ console.log(result)})
test(canshu=>{canshu()})
test(canshu=>{canshu(result=>{ console.log(result)})})
还有就是这个尚硅谷老师的回调地狱的问题,是不是那样的写法是回调呢?上面的例子是什么样的回调呢?
其实,我纠结的是老师的那句话,参数是函数。其实回调那里,
function request(cd){
cd();
}
就是证明可以直接写这个回调函数。
第二个问题就是这3层的怎么只写箭头函数的样式。
正常调用是
test(request(callback))?是这样的么?这个怕不是啊。这个不就是那个正常的调用么?函数结果在参数么。不同的地方在于,直接函数结果做参数,是函数运行完毕,返回值回来之后做参数。
这个回调,是把当做参数的函数放在自己的循环体内。其实,函数运行完毕,也是融入到函数体内啊。毕竟参数在函数体内的位置不同。它能还原成一个函数按顺序执行。看来我的理解还是不行
回调函数,就是自己运行过程中,调用其他的函数来执行一下。
像上面这样:想到哪里,写到哪里,用写具体化思维,比光想还好。特别是这么绕的地方。
===未完待续
//回调函数的作用,是异步的解决方式之一。
//另外,我记得有个排序,数组排序,使用回调函数,让回调函数来完成.或者,记得是特定的式子。不知道还有没有笔记啥都。
/** */
/*P109-异步-完成回调
//复制必要代码
var promise = new Promise(resovle=>{
setTimeout(()=>{
resovle('执行成功(promise内部语句)');
},2000);
});
//promise使用then来获取执行结果,
//这个方法在promise执行完毕之后才会执行,把resolve()的括号里的值当做参数
//VH:then()的参数是?什么函数样式?忘记了。单参数样式吧。箭头函数的单参数样式。
//VH:value只是一个参数代称,
promise.then(value => console.log(value));
console.log('在Promise之前执行(代码写在promise之后)');
//outputs:promise占用时间长的代码没有影响后面同步代码的执行
// index.js:96 在Promise之前执行(代码写在promise之后)
// index.js:95 执行成功(promise内部语句)
//end
/** */
//VH:补充,
//其实完整的promise含有一个回调函数(VH:寄生函数,2个参数resolve和reject)
//技术蛋老师 https://www.bilibili.com/video/BV1QV411a7Hu?share_source=copy_web
//尚硅谷 https://www.bilibili.com/video/BV1GA411x7z1?p=3&share_source=copy_web
//两个网页都是使用if...else...来分隔resolve()和reject(),
//VH:不同于其他函数的return,这里不用,只要使用resolve()就是返回值。而且后面使用then自动传入的是resolve无缝衔接。
//在一个网页教程中,说到resolve是必须,其他无所谓。
//我感觉promise像一个盒子,预设2个出口。无论怎么样,结果就从这里出来。【一个教程说promise语法是构造函数,功能是封装一个异步操作】
//关于异步和同步,多线程,多进程,我看了一些资料。没懂,但是可以暂时定下结论:异步是程序层面的执行顺序问题,多线程,多进程是涉及到CPU的问题。暂时这么理解吧。
/*其他地方的例子-技术蛋老师
//例子中常量isPregnat等于true,对应下面的打印结果。如果改为false,就是“男人成了老公”
const isPregnant = true;
const promise = new Promise((resolve, reject)=>{
if (isPregnant){
resolve('孩子他爹');
} else{
reject('老公');
}
});
promise
.then(name=>{
console.log(`男人成为了${name}!`);
})
.catch(name=>{
console.log(`男人成为了${name}!`);
})
.finally(()=>{
console.log(`男人和女人最终结婚了!`);
});
//outputs
// index.js:127 男人成为了孩子他爹!//如果isPregnat等于false,这句就是就是“男人成了老公”
// index.js:133 男人和女人最终结婚了!
//end
/** */
/*P110-异步-Promise异常捕获
//如果异步操作没有执行成功,需要抛出异常,我们可以给Promise接收到回调函数里面,加入第二个参数reject,
//是执行出错后,执行的方法,里面可以传递一些错误信息,然后这些就代表promise执行有异常了
//下面代码执行后,打印结果会出现Uncaught未捕获异常
var promise = new Promise((resovle,reject)=>{
setTimeout(()=>{
reject('执行失败(promise内部语句)');//Uncaught (in promise) 执行失败(promise内部语句)
},2000);
});
// promise.then(value => console.log(value));//标记216
console.log('在Promise之前执行(代码写在promise之后)');
//outputs
// index.js:217 在Promise之前执行(代码写在promise之后)
// index.html:1 Uncaught (in promise) 执行失败(promise内部语句)
//end
// 注意:如果没有标记216语句,那么打印结果是,错误索引是index.js:213
// index.js:213 Uncaught (in promise) 执行失败(promise内部语句)
//使用catch来捕获异常
//回调函数的参数就是promise执行失败传回来的错误信息,
//下面使用参数error变量名字接收错误信息,并在函数体内打印
//打印结果是promise中reject()中定义的错误信息,就没有uncaught的提示了
promise.catch(error=> console.log(error));
//outputs
// index.js:218 在Promise之前执行(代码写在promise之后)
// index.js:228 执行失败(promise内部语句)
//end
/** */
/*P111-异步-Promise 链式调用*/
/*链式调用
//Promise在每次调用then或者catch的时候,其实也都返回了一个新的promise对象,
//我们在它基础上继续调用.then或者.catch,比如说,我这里有一个例子,
//创建一个新的promise在1秒之后执行成功,返回一个数字1
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1);
},1000)
})
.then(value=>{
console.log(value);//标记249
return value+10;
})
.then(value=>{
console.log(value);//标记253
return new Promise(resolve=>resolve(value+20));
})
.then(value=>{
console.log(value);//标记257
});
//outputs
// index.js:249 1
// index.js:253 11
// index.js:257 31
//end
/** */
/*promise中的异常
//promise的reject异常,还有then里面throw抛出来的异常,
//除了跟在then后面用catch处理之外,还可以把catch放到最后一个then后面统一处理
new Promise((resolve,reject)=>{
setTimeout(()=>{
//resolve(1);//注释后改写,满足讲解异常处理的需要
reject('Promise 失败');//标记276
},1000)
})
.then(value=>{
console.log(value);
return value+10;
})
.then(value=>{
console.log(value);
return new Promise(resolve=>resolve(value+20));
})
.then(value=>{
console.log(value);
})
//这里添加.catch捕获异常,结果显示能够捕获到promise中的异常‘Promise 失败’(标记276)
//而且catch之前的所有的.then都没有继续执行
.catch(error=>{
console.log(error);//标记292
});
//outputs
//index.js:292 Promise 失败
//end
/** */
/*then中抛出的异常
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1);
},1000)
})
.then(value=>{
console.log(value);//标记307
throw 'then1异常';
return value+10;
})
.then(value=>{
console.log(value);
return new Promise(resolve=>resolve(value+20));
})
.then(value=>{
console.log(value);
})
//这里添加.catch捕获异常,结果显示能够捕获到第一个.then中throw的异常‘hen1异常’(标记307)
//第一个.then后的.then都不再执行,而且任何一个.then中如果throw异常,都是可以捕捉到的。
.catch(error=>{
console.log(error);//标记321
});
//outputs:
// index.js:307 1
// index.js:321 then1异常
//end
//以上就是promise的链式调用,每次调用.then或者.catch之后,
//它还会返回一个新的promise,基于它还可以使用其中的方法【?啥意思?】
/** */
/*P112-异步-多个Promise同时执行
//使用promise.all可以使多个promise同时执行,它会返回一个整体的大Promise,
//在所有的promise执行完之后,它会返回一个结果数组,分别是每个promise返回的值
//顺序和咱们传给它的promise数组元素的顺序是一样的,而不是按照返回结果快慢的顺序
//以下3个promise,其中嵌套的setTimeout,分别是1秒,2秒,0.5秒,
//但是最后Promise.all([p1,p2,p3])中数组按[p1,p2,p3]的顺序,
//then中返回值是个数组,元素也是按[p1,p2,p3]的顺序,不是执行快慢的顺序
var p1 = new Promise(resolve=>{
setTimeout(()=>{
resolve(1);
},1000)
});
var p2= new Promise(resolve =>{
setTimeout(()=>{
resolve(2);
},2000)
});
var p3= new Promise(resolve=>{
setTimeout(() => {
resolve(3);
}, 500);
});
Promise.all([p1,p2,p3]).then(values => console.log(values));
//outputs
// index.js:356 (3) [1, 2, 3]
//end
/** */
/*P113-异步-async和await*/
//是,但不完全是promise的语法糖
//咱们使用async关键字创建的函数,就等于说是创建了一个promise
//使用async和await的好处是:可以使用同步的代码样式,来执行异步的代码,比较直观
/*async
async function async1(){
setTimeout(() => {
console.log('async1 执行完毕');//标记373
}, 1000);
}
//打印async1()函数的返回值//VH:需要带()才会运行才有返回值
//返回的结果是一个Promise
async1();//async1 执行完毕
console.log(async1());//标记380
//output:
// index.js:380 Promise {<fulfilled>: undefined}
// __proto__: Promise
// [[PromiseState]]: "fulfilled"
// [[PromiseResult]]: undefined
// 2index.js:373 async1 执行完毕
//end
//注意,老师的课堂中,出现的结果是Promise{<resolved>:undefined},
//区别在于<fulfilled>和<resolved>
/** */
/*await的用法
//await可以用在async的函数里面,用来接收另一个async函数的结果
//await关键字必须在带async关键字的函数中调用
async function async1(){
let result2 = await async2();
console.log(result2);//标记398
}
async function async2(){
return new Promise(resolve =>{
setTimeout(() => {
resolve(10);
}, 1000);
});
}
//调用aysnc()函数,在1秒之后得到值10
async1();//index.js:398 10
/** */
/*await多个async的函数
//返回的顺序和代码定义的顺序是一样的,VH:比如下面例子,标记419和标记420的顺序。
//那么结果也是按这个顺序,而不是async函数中的setTimout执行快慢的顺序
async function async1(){
let result2 = await async2();
let result3 = await async3();
console.log(result2);//标记419
console.log(result3);//标记420
}
async function async2(){
return new Promise(resolve =>{
setTimeout(() => {
resolve(10);
}, 1000);
});
}
async function async3(){
return new Promise(resolve =>{
setTimeout(() => {
resolve(8);
}, 500);
});
}
async1();
//outputs:
// index.js:419 10
// index.js:420 8
//end
/** */
/*捕获异常
//async的函数中也可以抛出异常
//在await的时候,使用try...catch...来捕获异常
//如果不用try,catch的话,控制台会出现Uncaught(in index.js:80 promise)
//80是老师的视频中第一个async的最后的}的位置,对应标记463。
//VH:但是这里使用try...catch...就无法获取result3的值了。因为是let私有变量。如何二者兼得呢?
//例子中是第三个async函数中出错,那么在第一个async中使用await调用这个async3()的时候,就报错
//使用try...catch...监控let result3 = await async3()语句,准备捕获错误信息
//输出顺序,还是按照这个代码书写顺序来的。结果为先报错,再打印result2的值
async function async1(){
let result2 = await async2();
try {
let result3 = await async3();
} catch(e){
console.log(e);
}
console.log(result2);//标记459
//console.log(result3);//这个result3就不要了。
}//标记463
async function async2(){
return new Promise(resolve =>{
setTimeout(() => {
resolve(10);
}, 1000);
});
}
async function async3(){
return new Promise((resolve,reject) =>{
setTimeout(() => {
reject('执行出错');
}, 500);
});
}
async1();
//outputs
// index.js:457 执行出错
// index.js:459 10
//end
/** */