js處理異步的幾種方式

作者:管理員 日期:2018-10-22 瀏覽:

Javascript語言的執行環境是"單線程"(single thread,就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務,以此類推)。

這種模式的好處是實現起來比較簡單,執行環境相對單純;壞處是只要有一個任務耗時很長,后面的任務都必須排隊等著,會拖延整個程序的執行。常見的瀏覽器無響應(假死),往往就是因為某一段Javascript代碼長時間運行(比如死循環),導致整個頁面卡在這個地方,其他任務無法執行。

為了解決這個問題,Javascript語言將任務的執行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。

“同步模式" 就是上一段的模式,后一個任務等待前一個任務結束,然后再執行,程序的執行順序與任務的排列順序是一致的、同步的;"異步模式"則完全不同,每一個任務有一個或多個回調函數(callback),前一個任務結束后,不是執行后一個任務,而是執行回調函數,后一個任務則是不等前一個任務結束就執行,所以程序的執行順序與任務的排列順序是不一致的、異步的。

“異步模式" 非常重要。在瀏覽器端,耗時很長的操作都應該異步執行,避免瀏覽器失去響應,最好的例子就是Ajax操作。在服務器端,"異步模式"甚至是唯一的模式,因為執行環境是單線程的,如果允許同步執行所有http請求,服務器性能會急劇下降,很快就會失去響應。

 

本文主要說明的是 處理異步的幾種方法

一、回調函數(callback)

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

翻譯:回調是一個函數被作為一個參數傳遞到另一個函數里,在那個函數執行完后再執行。( 也即:B函數被作為參數傳遞到A函數里,在A函數執行完后再執行B )

假定有兩個函數f1和f2,后者等待前者的執行結果。

f1();
f2();

如果f1是一個很耗時的任務,可以考慮改寫f1,把f2寫成f1的回調函數。

復制代碼
function f1(callback){
  setTimeout(function () {
    // f1的任務代碼
    callback();
  }, 1000);
}
// 執行
f1(f2)
復制代碼

采用這種方式,我們把同步操作變成了異步操作,f1不會堵塞程序運行,相當于先執行程序的主要邏輯,將耗時的操作推遲執行。

回調函數是異步編程最基本的方法,其優點是簡單、容易理解和部署,缺點是不利于代碼的閱讀和維護,各個部分之間高度耦合(Coupling),流程會很混亂,而且每個任務只能指定一個回調函數。

注意 區分 回調函數和異步

  回調并不一定就是異步。他們自己并沒有直接關系。

簡單區分 同步回調 和 異步回調

同步回調 :

實例代碼

復制代碼
function A(callback){
    console.log("I am A");
    callback();  //調用該函數
}
function B(){
   console.log("I am B");
}
A(B);
復制代碼

異步回調:因為js是單線程的,但是有很多情況的執行步驟(ajax請求遠程數據,IO等)是非常耗時的,如果一直單線程的堵塞下去會導致程序的等待時間過長頁面失去響應,影響用戶體驗了。

如何去解決這個問題呢,我們可以這么想。耗時的我們都扔給異步去做,做好了再通知下我們做完了,我們拿到數據繼續往下走。

復制代碼
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);   //第三個參數決定是否采用異步的方式
xhr.send(data);
xhr.onreadystatechange = function(){
    if(xhr.readystate === 4 && xhr.status === 200){
       ///do something
    }
}
復制代碼

上面是一個代碼,瀏覽器在發起一個ajax請求,會單開一個線程去發起http請求,這樣的話就能把這個耗時的過程單獨去自己跑了,在這個線程的請求過程中,readystate 的值會有個變化的過程,每一次變化就觸發一次 onreadystatechange  函數,進行判斷是否正確拿到返回結果。

之前在學習 nodejs時也會遇到這樣的問題

復制代碼
var fs=require('fs');
//console.log('1');
//fs.readFile('mime.json',function(err,data){
//    //console.log(data);
//    console.log('2');
//})
//console.log('3');
function getMime(){
    //1
    fs.readFile('mime.json',function(err,data){
        //console.log(data.toString());
        return data;//3
    })
    //2
    //return '123';
}
console.log(getMime());  /*由于異步操作沒有拿到數據,如何解決,通過異步操作*/
復制代碼

解決的 辦法 是

復制代碼
var fs=require('fs');
function getMime(callback){
    fs.readFile('mime.json',function(err,data){
        callback(data);
    })
}
getMime(function(result){
    console.log(result.toString());
})
首頁
電話
短信
聯系
在線客服系統
在線客服
QQ客服
辽宁十一选五前三技巧