同步、异步

函数必须执行完成才能继续进一步执行程序,这样就叫做同步。
不必得到函数执行的结果,可以先进行其他的程序,就叫做异步。
js是单线程的,他的主线程上的所有任务都是同步任务,意思就是只有上一个任务执行完毕,才会执行下一个任务。这样会导致一些十分耗时的任务会阻碍后续任务的执行,因此出现了异步任务。
异步任务会进入宏任务队列,当异步任务准备好了可以执行时,就会通知主线程准备完毕。而在主线程所有任务执行完了之后,才会进行宏任务队列中异步任务的执行,处理异步任务。

异步任务的顺序

  1. function load(src, resolve) {
  2. let script = document.createElement("script");
  3. script.src = src;
  4. script.onload = resolve;
  5. document.body.appendChild(script);
  6. }
  7. load("1.js", () => {
  8. before();
  9. });
  10. load("2.js", () => {
  11. after();
  12. });
  13. console.log("最优先任务");
  14. //1.js
  15. function before() {
  16. first = "第一步加载完成";
  17. console.log(first);
  18. }
  19. //2.js
  20. function after() {
  21. console.log(first + "第二步加载完成");
  22. }

异步任务的执行顺序是不确定的,一次上述代码可能会出现下图所示的结果。
image.png

回调函数

函数被其他函数调用就是回调。
首先创建一个函数,但是不调用它,在未来的某个时间点或者某个地点,函数被调用,这时就产生了回调。

使用回调函数解决异步问题

因此为了确保异步函数执行的顺序,我们需要回调函数。
改进上述代码。这样我们就可以永远确保2.js在1.js后执行。

  1. function load(src, resolve) {
  2. let script = document.createElement("script");
  3. script.src = src;
  4. script.onload = resolve;
  5. document.body.appendChild(script);
  6. }
  7. load("1.js", () => {
  8. before();
  9. load("2.js", () => {
  10. after();
  11. });
  12. });
  13. console.log("最优先任务");

异步任务的多结果处理

如果异步函数有两个结果怎么办?
例如需要分辨异步结果的正确与否的情景下,如何使回调函数正确区分?
1.使回调函数接受两个参数(error,data)
2.使用两个回调函数,不同情况调用不同函数(success、fail)

使用回调函数的缺点

1.不够规范,不同的人命名不同,例如也有人命名为done、error
2.容易产生回调地狱
3.很难进行错误处理(try…catch也很难进行错误处理)