JS之異步概念


概念 什么是JS異步

異步加載也叫非阻塞模式加載,瀏覽器在下載js的同時,還會執行后續的頁面處理.

何時需要異步

1 需要等待的情況

2 在等待過程中不能像alert一樣阻塞程序運行

3 等待的情況需要異步

使用場景:

1 定時任務setTimeout, setInterval

console.log(100);
 setTimeout(function(){
   console.log(200);
 },1000); //異步執行,非阻塞並不妨礙后續代碼執行
 console.log(300);
//執行順序為100 300 200

2   網絡請求 ajax 動態<img> 加載

console.log("start");
 var img=document.createElement("img");
 img.onload=function(){
   console.log("loaded");
 }
 img.src="https://ps.ssl.qhimg.com/sdmt/75_135_100/t01525fd8d9773b149f.jpg";
 document.body.append(img);
 console.log("end");
 //執行順序是 start end loaded 圖片的加載時異步的

3  事件綁定

console.log("start");
 document.getElementById("btn").addEventListener("click",function(){
   console.log("clicked");
 });
 console.log("end");
 //執行順序是start ,end 如果點擊才執行clicked 如果不點永遠不執行 也是異步的

典型的同步加載的例子:

console.log(100);
 alert(200);
 console.log(300);
 //同步打印100,彈出200,打印300,取決於按下‘確定’框的時間,不按就一直卡頓在那

同步或非同步,表明着是否需要將整個流程按順序地完成

阻塞或非阻塞,意味着你調用的函數會不會立刻告訴你結果

二、在js中的阻塞與同異步

你有一個函數和一段程序。

2.1 js中的同步阻塞

// 這是一個阻塞式函數, 將一個文件復制到另一個文件上
function copyBigFile(afile, bfile){
    var result = copyFileSync(afile,bfile);
    return result;
}

調用這個”copyBigFile()”函數,將一個大文件復制到另一個文件上,將耗時1小時。意味着這個函數的將在一個小時之后返回。

//這是一段程序
console.log("start copying ... ");    
var a = copyBigFile('A.txt', 'B.txt');  //這行程序將耗時1小時
console.log("Finished");   // 這行程序將在一小時后執行
console.log("處理一下別的事情");  // 這行程序將在一小時后執行
console.log("Hello World, 整個程序已加載完畢,請享用"); // 這行程序將在一小時后執行

以上的程序就是一個同步阻塞的例子,因為copyFileSync函數返回值的過程需要漫長的時間,所以線程也無法繼續執行下去,只能等待。

2.2 js中的同步非阻塞

// 這是一個非阻塞式函數
// 如果復制已完成,則返回 true, 如果未完成則返回 false
function copyBigFile(afile,bfile){
    var copying = copyFileAsync(afile, bfile);
    var isFinished = !copying;
    return !isFinished; 
}

調用這個函數將立刻返回結果,然后你的程序就可以寫成

console.log("start copying ... ");    
while( a = copyBigFile('A.txt', 'B.txt')){
  console.log("在這之間還可以處理別的事情");
} ;  
console.log("Finished");   // 這行程序將在一小時后執行
console.log("Hello World, 整個程序已加載完畢,請享用"); // 這行程序將在一小時后執行

一個非阻塞式的函數,給你的編程帶來了更多的便利,你可以在長IO操作的同時,寫點其他的程序,提高效率。執行結果如下

start copying ... 在這之間還可以處理別的事情 在這之間還可以處理別的事情 在這之間還可以處理別的事情 ... Finished Hello World, 整個程序已加載完畢,請享用

2.3 js中的異步非阻塞

我們看到,一個非阻塞式的函數能給我們編程帶來許多靈活性,我們喜歡非阻塞式的函數。 
但是,又可以看到同步的程序需要在一個循環中輪詢結果,循環里面的程序會被執行好多遍,所以並不好控制來寫一些正常的程序,很難再利用起來。 
所以我們需要一種更為合理的方式對非阻塞式的函數進行利用。 
也就是我不會主動地去詢問結果,而是當你有了結果的時候再來通知我。 
// 這是一個非阻塞式函數 
// 如果復制已完成,則返回 true, 如果未完成則返回 false

//非阻塞式的有異步通知能力的函數
//以下不需要看懂,只用知道這個函數會在完成copy操作之后,執行success
function copyBigFile(afile,bfile, callback){
    var copying = copyFileAsync(afile, bfile, function(){ callback();});
    var isFinished = !copying;
    return !isFinished; 
}

這個函數不同於上一個同步非阻塞函數的地方在於,它具有通知功能,也就是說,它能夠在完成操作之后主動地通知程序,“我完成了”。於是有程序如下,

console.log("start copying ... ");    
copyBigFile("A.txt","B.txt", function(){
          console.log("Finished");   //一個小時后被執行
          console.log("Hello World, 整個程序已加載完畢,請享用"); //一個小時后被執行
          })
console.log("干別的事情"); 
console.log("做一些別的處理"); 

程序在調用copyBigFile函數之后,可以立即獲得返回值,線程沒有被阻塞住,於是還可以去干些別的事情,然后當copyBigFile完成之后,會執行指定的函數。所以程序的輸出應為,

start copying ...
干別的事情
做一些別的處理
Finished
Hello World, 整個程序已加載完畢,請享用

在這種情況下,程序更容易控制,流程更為清晰。一些“別的事情”可以在函數還未通知之前進行處理,充分地提高了線程的利用效率。

  

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM