零.前言
JavaScript(一)---【js的两种导入方式、全局作用域、函数作用域、块作用域】-CSDN博客
JavaScript(二)---【js数组、js对象、this指针】-CSDN博客
JavaScript(三)---【this指针,函数定义、Call、Apply、函数绑定、闭包】-CSDN博客
JavaScript(四)---【执行上下文、hoisting(提升)、严格模式、事件】-CSDN博客
JavaScript(五)---【DOM】-CSDN博客
一.回调
1.1简介
“回调”是作为参数传递给另一个函数的函数
这种技术允许函数调用另一个函数,回调函数可以在另一个函数完成后运行
1.2什么时候使用回调函数
现在假设有一个业务需求:”先计算两个数的和,再将和输出,并且我们可以随时终止输出和“
或许有的读者会很轻松的写出如下代码:
<script>
function printData(result){
console.log(result);
}
function calculator(x,y){
let sum = x + y;
return sum;
}
let result = calculator(5,5);
printData(result);
</script>
我们将计算和输出分别用两个函数来完成,但是这样会有一个问题,那就是每次我们都需要使用两个函数,比较麻烦。
此时,可能有读者又会写出另一种风格的代码:
<script>
function printData(result){
console.log(result);
}
function calculator(x,y){
let sum = x + y;
printData(sum);
}
calculator(5,5);
</script>
在“calculator函数中调用printData函数”,这样每次只需要调用一次“calculator”函数就可以了,但是这样仍然有一个问题,那就是:“无法随时禁止打印的过程”
那么此时就用到我们的回调函数了,将printData函数作为参数传给calculator函数即可。
但在使用前,我们还是有必要先说明一下怎么使用回调函数。
1.3回调函数的使用
回调函数的使用非常简单,将需要在A函数调用的B函数作为参数传递给A函数即可。
此时B函数就成为A函数的一个形参,而在A函数中就可以利用形参来代指B函数。
例如:
<script>
function B(){
console.log("我是B函数");
}
function A(myB){
console.log("我是A函数");
myB();
}
A(B);
</script>
效果:
注意:
在将B函数作为参数传递给A函数时,实参不能带有括号,只需要写“函数名”即可
而在A函数中使用形参“myB”代指B函数时,则需要加上“括号”
1.4问题的解决
那么搞明白回调函数的使用之后,我们来是用回调函数解决这个问题。
业务需求:“先计算两数之和,再输出两数之和,并且可以随时终止输出的过程”
解决思路:“我们将printData函数作为参数传递给calculator函数,在calculator函数中调用printData函数用来完成计算并输出的功能,此时如果需要终止输出的过程那么可以给calculator的形参传递一个空值,用来表示此时不需要输出”
<script>
function printData(result){
console.log(result);
}
function calculator(x,y,myData){
let sum = x + y;
if (myData)
myData(sum);
}
calculator(5,5,printData); //此时需要输出
calculator(10,10,undefined) //此时不需要输出
</script>
效果:
二.异步
2.1简介
如果大家接触过“多线程”的概念,那么“异步”应该是非常好理解的。
一个相对好理解的说法就是:“异步就是在同一时间运行多个代码段(函数、代码块等)”
而官方的说法:“与其它函数并行运行的函数称为异步”
给大家举一个例子:“在某一时刻,我们需要同时获得a+b和a*b的值该怎么办?如果顺序执行a+b和a*b终究会有时间差,并不是同时获得。那么此时就用到了异步了,将a+b和a*b两个运算过程,同时进行”
2.2常见的异步函数
在js中内置了多个异步函数,便于我们调用,如果需要使用更多的异步函数,需要用到js库等
下面作者将论述几个常见的异步函数
2.3等待超时函数
等待超时函数:“setTimeout()”可以指定超过指定时间后,自动执行某个函数
使用方法:
setTimeout(执行函数名,超时时间(ms))
ps:使用setTimeout会返回一个超时函数变量(该变量存储了超时函数id)
结束方法:
使用:“clearTimeout(超时函数变量)”来强制结束
注意:强制结束应该在超时函数执行前使用,否则无效
例如:
<script>
function myFunction(){
console.log("我被调用了");
}
setTimeout(myFunction,3000)
</script>
以上这个函数将会在:“3秒后自动被调用”
可以发现setTimeout的参数是一个函数,也就是说setTimeout是一个“回调函数”
2.4等待间隔函数
等待间隔函数:“setInterval()”可以指定每隔指定时间,执行一次函数,直到程序被关闭或者人为结束
(ps:该函数用的特别多)
使用方法:
setInterval(函数名,指定时间(ms))
ps:使用setInterval函数会返回一个异步函数变量(这个变量存储该异步函数的id)
人为结束“setInterval”函数的方法:“使用clearIntervar(异步函数变量)”来强制结束“setInterval”
<script>
function interVal(){
console.log("我是等待间隔函数,我被调用了.");
}
function stopInterVal(){
clearInterval(time);
}
var time = setInterval(interVal,1000);
</script>
以上是一个简单的开启关闭示例
三.promise
3.1简介
promise是一个js对象,它链接“生成代码”和“消费代码”
- “生成代码”(Producing code):指需要一些时间的代码
- “消费代码”(Consuming code):指必须等待结果的代码
3.2使用方式
let myPromise = new Promise(function(myResolve, myReject) { // "Producing Code"(可能需要一些时间) myResolve(); // 成功时 myReject(); // 出错时 }); // "Consuming Code" (必须等待一个兑现的承诺) myPromise.then( function(value) { /* 成功时的代码 */ }, function(error) { /* 出错时的代码 */ } );
注意:
当“执行代码”也就是“消费代码”获得结果时,它必须调用两个回调函数之一:“myResolve、myReject”
而在“消费代码”中,“function(value)代表myResolve、function(error)代表myReject”
例如:
function myDisplayer(some) {
document.getElementById("demo").innerHTML = some;
}
let myPromise = new Promise(function(myResolve, myReject) {
let x = 0;
// 生成代码(这可能需要一些时间)
if (x == 0) {
myResolve("OK");
} else {
myReject("Error");
}
});
myPromise.then(
function(value) {myDisplayer(value);},
function(error) {myDisplayer(error);}
);
四.Async和Await
4.1简介
使用async关键字,可以使我们更方便的使用promise函数,而不是创建一个promise对象。
通过在函数前面加入关键字“async”可以使函数返回“promise”
使用“await”关键字,可以使函数等待“promise”
4.2使用方法
例如:
async function myFunction() {
return "Hello";
}
//等同于
async function myFunction() {
return Promise.resolve("Hello");
}
而使用“async”和“await”可以使我们更方便的完成promise的操作,而promise操作的实质就是更安全的进行“异步操作”,因为promise可以进行失败逻辑判断处理
再例如:
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript async / await</h1>
<p>请等待 3 秒(3000 毫秒)让此页面发生变化。</p>
<h1 id="demo"></h1>
<script>
async function myDisplay() {
let myPromise = new Promise(function(myResolve, myReject) {
setTimeout(function() { myResolve("I love You !!"); }, 3000);
});
document.getElementById("demo").innerHTML = await myPromise;
}
myDisplay();
</script>
</body>
</html>
上面这个代码就是更安全的“异步操作”