1. 程式人生 > >jQuery.deferred()方法

jQuery.deferred()方法

 如果不懂  $.when() 方法的請看我的上一篇部落格

/**
 * 定義一個很耗時的 wait 函式
 * 這個地方不呼叫 resolve 就可以執行, 是因為 wait 並不是一個 promise 或者 deferred 
 * done()方法會立即執行,起不到回撥函式的作用
 * $.when()的引數只能是deferred物件,所以必須對wait()進行改寫
 */
var wait = function() {
    var tasks = function() {
        console.log('執行完畢');
    }
    setTimeout(tasks, 2000)
}
$.when(wait())
    .done(function() { console.log("哈哈,成功了!"); })
    .fail(function() { console.log("出錯啦!"); });

/** 
 * 改寫 wait()
 * 再 wait 函式執行完之後, 函式內部呼叫了成功的方法就會自動執行 done 函式
 * 當然你也可以 呼叫失敗的方法, 只需要把 `dtd.resolve()` 改成 `dtd.reject()` 即可
 * Deferred 是有三個狀態的
 * 第一個狀態 : 待開始的狀態
 * 第二個狀態 : 成功時的狀態
 * 第三個狀態 : 失敗時的狀態
 */

// 第一種寫法(沒有封裝)
var dtd = $.Deferred() // 建立一個 Deferred 物件
var wait = function(dtd) { // 要求傳入一個 deferred 物件, 不然這個函式沒有意義了
    var tasks = function() {
        //這裡可以有大量的複雜操作
        console.log("執行完畢"); // 執行完畢
        dtd.resolve() // 表示非同步任務已經完成, 改變 deferred 物件的狀態

        // dtd.reject() // 表示非同步任務失敗, 改變 deferred 物件的狀態
    }
    setTimeout(tasks, 2000) // 等待 2m 後執行
    return dtd // 一定要有返回值, 並且 一定是這個 物件
}
$.when(wait(dtd))
    .done(function() { console.log("哈哈,成功了!"); }) // 哈哈,成功了!
    .fail(function() { console.log("出錯啦!"); });

// 第二種寫法 (封裝版)
function waitHandle() {
    var dtd = $.Deferred()
    var wait = function(dtd) {
        var tasks = function() {
            console.log('執行完畢') // 執行完畢
            dtd.resolve()

            // dtd.reject()
        }
        setTimeout(tasks, 2000)
        return dtd
    }
    return wait(dtd)
}
var w = waitHandle()

// 此處同樣可是使用 then 方法來呼叫
w.then(function() {
    console.log('ok 1'); // ok 1
}, function() {
    console.log('err 1');
}).then(function() {
    console.log('ok 1'); // ok 1
}, function() {
    console.log('err 1');
})

/**
 * 這樣呢 : 有一個弊端就是, 可以手動修改狀態.
 * 舉梨 : 比如 我們函式中, 定義的是 dtd.resolve() 方法,但是我們再程式的最後一行加上 w.reject() 
 * 結果 就很有意思了, 會再程式以執行的時候, 改變 dtd 的狀態, 然後立即執行 `done()`, 等到 延時器 結束的時候再執行 `console.log('執行完畢')`
 * 這樣就不是我們想要的了
 * 所以 : 就引出了 deferred.promise() 方法.
 */

// + w.resolve()