异步编程技术使你的程序,可以在执行一个可能长期运行的任务的同时,继续对其他事件做出反应而不必等待任务完成。与此同时,你的程序也将在任务完成后显示结果。
浏览器提供的许多功能(尤其是最有趣的那一部分)可能需要很长的时间来完成,因此需要异步完成,例如:
- 使用 fetch()发起 HTTP 请求
- 使用 getUserMedia()访问用户的摄像头和麦克风
- 使用 showOpenFilePicker()请求用户选择文件以供访问
因此,即使你可能不需要经常实现自己的异步函数,也很可能需要正确使用它们。
同步编程
const name = "mary";
const greeting = `Hello,my name is ${name}!`;
console.log(greeting);
- 声明了一个叫做
name
的字符串常量 - 声明了另一个叫做
greeting
的字符串常量(并使用了name
常量的值) - 将
greeting
常量输出到 JavaScript 控制台中。
实际上浏览器是按照我们书写代码的顺序一行一行地执行程序的,浏览器会等待代码的解析和工作,在上一行完成后才会执行下一行,因为每一行新的代码都是建立在前面代码的基础之上的,
这也使得它成为一个同步程序。
事实上,调用函数的时候也是同步的:
function makeGreeting(name){
return `Hello,my name is ${name}!`;
}
const name = "Mike";
const greeting = makeGreeting(name);
console.log(greeting);
在这里 makeGreeting()
就是一个同步函数,因为在函数返回之前,调用者必须等待函数完成其工作。
耗时同步函数
当用户点击“生成素数”按钮时,这个程序将使用一种非常低效的算法生成一些大素数。你可以控制要生成的素数数量,这也会影响操作需要的时间。
在HTML文件中:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<label for="quota">素数个数:</label>
<input type="text" id="quota" name="quota" value="1000000" />
<button id="generate">生成素数</button>
<button id="reload">重载</button>
<div id="output"></div>
<script src="../scripts/main5.js" defer></script>
</body>
</html>
在JS文件中:
function generatePrimes(quota){
function isPrime(n){
for (let c = 2;c<=Math.sqrt(n);++c){
if(n % c === 0){
return false;
}
}
return true;
}
const primes = [];
const maximum = 1000000;
while(primes.length < quota){
const candidate = Math.floor(Math.random() * (maximum + 1));
if (isPrime(candidate)) {
primes.push(candidate);
}
}
return primes;
}
document.querySelector("#generate").addEventListener("click", () => {
const quota = document.querySelector("#quota").value;
const primes = generatePrimes(quota);
document.querySelector("#output").textContent =
`完成!已生成素数${quota}个。`;
});
document.querySelector("#reload").addEventListener("click", () => {
document.location.reload();
});
结果展示:
此时加入一个文本框进行输入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<label for="quota">素数个数:</label>
<input type="text" id="quota" name="quota" value="1000000" />
<button id="generate">生成素数</button>
<button id="reload">重载</button>
<textarea id="user-input" rows="5" cols="62">点击“生成素数”按钮后试着在这里输入</textarea>
<div id="output"></div>
<script src="../scripts/main5.js" defer></script>
</body>
</html>
结果展示:
发现当 generatePrimes()
函数运行时,我们的程序完全没有反应:用户不能输入任何东西,也不能点击任何东西,或做任何其他事情,这就是耗时的同步函数的基本问题。