Callback Hell:一點迷宮

AJAX,非同步 JavaScript 及 XML(Asynchronous JavaScript and XML,AJAX)的「非同步」,指的是電腦處理某東西時,不用馬上完成,而是等到某個時候再處理。至於「某個時候」是什麼時候,要視情況而定。

AJAX 就是把請求先送到伺服器,等到某個時候再處理。在 AJAX,「某個時候」就是指伺服器有所回應時,無論它成功或失敗。用 jQuery 來看,就是這樣:

$.ajax({
    url:"//example.com",
    error: function(jqXHR, textStatus, errorThrown)
    {
        /* 伺服器回應失敗的話怎麼做 */
    },
    success: function(data)
    {
        /* 伺服器回應成功的話怎麼做 */
    }
});

但如果我們要做很多次 AJAX 請求,故事會變成這樣……

$.ajax({
    /* 略 */
    success: function(data)
    {
        $.ajax({
        /* 略 */
            success: function(data)
            {
            /* 略 */
                $.ajax({
                /* 略 */
                success: function(data)
                    {
                        /* 略 */
                    }
                });
            }
        });
    }
});

感覺就像在走迷宮,對否? 那要怎麼做才好呢?

其實有很多方法。最基本、最簡單的方法,就是把它們變成一個個函式,然後拆開來:

function first_ajax()
{
    $.ajax({
        success: function(data)
        {
            second_ajax(data)
        }
    });
}
function second_ajax(sa_input)
{
    $.ajax({
        success: function(data)
        {
            third_ajax(data)
        }
    });
}
function third_ajax(ta_input)
{
    $.ajax({
        success: function(data)
        {
            /* 省略 */
        }
    });
}

我曾經考慮使用 ES6 的語法,不過看到拆成 function 才發現萬變不離其宗:要拆掉迷宮,首先要知道怎麼拆,再考慮要用什麼工具拆:

Before looking at more advanced solutions, remember that callbacks are a fundamental part of JavaScript (since they are just functions) and you should learn how to read and write them before moving on to more advanced language features, since they all depend on an understanding of callbacks. 「在考慮更進階的解法前,謹記回呼是 JavaScript 的基礎(因為它們就只是函式)、你也應該在使用更進階的功能之前,先理解怎麼看、怎麼寫回呼,因為它們需要依賴你對回呼的理解。」 src

如果真的要用上更高階的作法,我建議參考 Calpa 的 異步操作見聞錄


前端的變化很快,快到有文章嘲諷 JS 框架的發展速度。但很多時候,其實會在想,自己是不是真的需要這些東西…… 我想起新手機的抉擇、還有支付寶的爭論。

參考資料