javascript - 同步方式寫非同步到底指什麼?
天蓬老师
天蓬老师 2017-07-05 10:52:36
0
4
959

同步不就是同步,非同步不就是非同步嗎?同步方式寫異步到底指什麼?

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回覆(4)
扔个三星炸死你

非同步呼叫對於當前線程來說,是非阻礙的,所以要想知道非同步處理是否完成,或者是否出錯,通常都是透過事件或回調來實現的,這在 Node.js 比比皆是。 Ajax 就是很典型的非同步調用,以 jQuery.ajax 為例

$.getJSON("http://api.youapp.com/resouce1")
    .done(function(jo) {
        console.log("api resouce1 返回的是", jo);
    });

jQuery 的 Ajax 回傳的是 jQuery 的 Promise 對象,一般習慣上我們會使用 done() 回呼來處理呼叫完成之後的事情。但實際它也有標準Promise 的then(),所以上面的done 是可以改成then 的,但是要注意,done 是以事件的形式註冊回調,它返回當前這個Promise 物件,可以鍊式呼叫註冊若干個回呼。而 then 回傳的是另一個 Promise 物件(標準 Promise 規範),鍊式呼叫的話,每次呼叫並非作用在同一個 Promise 物件上。

如果在一個回調中需要進行另一個非同步調用,就需要在回調中註冊另一個回調。例如要取得某個數據,就需要先從api1 取得某個值,再用這個值去api2 取得某個資源,再用這個資源中的某個值去api3 取得這個值,這樣的回呼寫出來會像這樣:

$.getJSON("http://api.youapp.com/resouce1")
    .then(function(jo) {
        $.getJSON("http://api.youapp.com/resouce2?id=" + jo.blaId)
            .then(function(jo2) {
                $.getJSON("http://api.youapp.com/resouce3?xxx=" + jo2.xxxValue)
                    .then(function(value) {
                        console.log("总算拿到了", value);
                    });
            });
    });

這才三層……很可怕的形式。這種形式被稱為「回調地獄」。

大家想了很多辦法來解決這種問題,Promise 就是其一,但是 Promise 仍然無法完全擺脫這種形式。 co 庫也是解決方案之一,同樣無法完美擺脫。

不過 ES2017 引入了 async/await,也就是所謂的以同步的形式寫異步,例如上面那段程式碼可以改寫成


async function xxx() {
    const jo = await $.getJSON("http://api.youapp.com/resouce1");
    const jo2 = await $.getJSON("http://api.youapp.com/resouce2?id=" + jo.blaId);
    const value = await $.getJSON("http://api.youapp.com/resouce3?xxx=" + jo2.xxxValue);
    console.log("总算拿到了", value);
}

async/await 消除了回調,所以看起來跟寫非異步(即同步)程式碼一樣。

參考:

  • 閒聊非同步調用「扁平」化

  • 從地獄到天堂,Node 回調轉向 async/await

  • 理解 JavaScript 的 async/await

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!