回調、使用Promise封裝ajax()、Promise入門

回調、使用Promise封裝ajax()、Promise入門

1 回調是啥

call a function
call a function backgit

callbackgithub

看這裏:Callback(回調)是什麼?---方應杭知乎ajax

callback 是一種特殊的函數, 這個函數被做爲參數傳給另外一個函數去調用。這樣的函數就是回調函數。

1.1 回調例子

Callback 很常見
$button.on('click', function(){})
click後面的 function 就是一個回調,由於「我」沒有調用過這個函數,是 jQuery 在用戶點擊 button 時調用的(當用戶點擊以後,這個函數才執行,如今我只是傳了一個參數,這個參數是一個點擊後要執行的函數)。json

div.addEventListener('click', function(){})
click 後面的 function 也是一個回調,由於「我」沒有調用過這個函數,是瀏覽器在用戶點擊 button 時調用的。segmentfault

通常來講,只要參數是一個函數,那麼這個函數就是回調。promise

請看我寫的封裝的簡易jQuery.ajax()中的successFN就是一個回調函數.瀏覽器

只有在請求成功並接收到響應的時候纔會執行這個success函數,這就是回調.傳一個函數做爲參數可是不執行,讓另外一個函數去調用,就是回調函數服務器

1.2Callback 有點反直覺

callback 有一點「反直覺」。
好比說咱們用代碼作一件事情,分爲兩步:step1( ) 和 step2( )。app

符合人類直覺的代碼是:異步

step1()
step2()
callback 的寫法倒是這樣的:

step1(step2)
爲何要這樣寫?或者說在什麼狀況下應該用這個「反直覺」的寫法?

通常(注意我說了通常),在 step1 是一個異步任務的時候,就會使用 callback。

什麼是異步任務呢?

2.什麼是異步?

「每日一題」什麼是異步?---方應杭知乎
下一篇博客再詳細記錄吧

3. $.Ajax()Promise 是什麼?如何用?

「每日一題」Promise 是什麼?

代碼都在這裏

3.1 $.Ajax()中的promise

若是不使用promise,$.ajax請求的時候成功和失敗的回調函數是寫在參數裏的,他是對象參數的一個值

$.ajax({
        method:"post",
        url:"/xxx",
        data:"username=mtt&password=1",
        dataType:'json',
        success:()=>{}//成功後的回調函數
        error:()=>{}//失敗後的回調函數
    }
    )

若是使用jQuery.axja()發送請求,並使用promise,代碼以下

let myButton = document.getElementById('myButton');

function success(responseText){
    console.log("成功")
    console.log(responseText);//responseTex
}
function fail(request){
    console.log("失敗")
    console.log(request);
}
myButton.addEventListener("click",(e)=>{
    //使用ajax
    $.ajax({
        method:"post",
        url:"/xxx",
        data:"username=mtt&password=1",
        dataType:'json'//預期服務器返回的數據類型,若是不寫,就是響應裏設置的
    }
    ).then(success,fail)//$.ajax()返回一個promise
})

成功的結果:
PrgSzV.png

換一個不存在的地址/mtt失敗的結果
PrcXIs.png

$.ajax()函數會返回一個promise,而後在後面.then(success,fail)時候,若是成功了就會調用第一個參數裏的函數即success函數,若是失敗了就會調用第二個參數的函數即fail函數.

3.1.1 promise的第一個意義

promise的第一個意義:不用記住成功和失敗究竟是success,仍是successFN或者是fail或者是error,不用記住函數名字.只須要知道成功是第一個參數,失敗時第二個參數,好比這樣寫

//使用ajax
    $.ajax({
        method:"post",
        url:"/xxx",
        data:"username=mtt&password=1",
        dataType:'json'//預期服務器返回的數據類型,若是不寫,就是響應裏設置的
    }
    ).then((responseText)=>{console.log(responseText)},()=>{console.log("失敗")})//$.ajax()返回一個promise

徹底不須要寫函數名

3.1.2promise的第二個意義

若是你須要對一個結果進行屢次處理,能夠這樣寫:

$.ajax({
        method:"post",
        url:"/xxx",
        data:"username=mtt&password=1",
        dataType:'json'//預期服務器返回的數據類型,若是不寫,就是響應裏設置的
    }
    ).then((responseText)=>{
        console.log(responseText)
        return responseText;//若是要對結果進行屢次處理,就在這裏return,第二次then就會獲得這個return的數據
    },()=>{
        console.log("失敗")
    }).then(//開始第二次then
        (上一次return的結果)=>{
            console.log("第二次處理")
            console.log(上一次return的結果)
        },
        ()=>{
            //第二次處理失敗結果
        }
    )

結果:
Prg0eg.png
看到第二個then裏的函數吧第一次then裏return的結果當作參數,繼續處理.
因此promise的好處是若是想再次用兩個函數,即再次對結果進行處理,就再then 一下,不須要再次取名字了
then的中文含義:而後!

以上就是ajax中promise的簡單使用,那麼如何本身封裝一個呢?

PS: ajax()函數參數裏的 dataType:'json'//預期服務器返回的數據類型,若是不寫,就是響應裏設置的 即:
ajax方法中的dataType:預期服務器返回的數據類型。若是不指定,jQuery 將自動根據 HTTP 包 MIME 信息來智能判斷。

4封裝一個相似$.Ajax()中的Promise的簡易版本(皮毛,之後深刻)

接下來回到咱們本身封裝的jQuery.Ajax()代碼.咱們以此爲基礎繼續來封裝promise

之前封裝的代碼在這裏
也能夠看我前一篇博客,裏面有如何封裝Ajax()的方法和詳細過程.

原來的封裝Ajax()代碼核心部分:

window.jQuery.ajax = ({method,path,body,successFn,failFn,headers})=>{//ES6語法
    
    let request = new XMLHttpRequest();
    request.open(method,path);//配置

    for (const key in headers) {//遍歷header,設置響應頭
    let value = headers[key];
        request.setRequestHeader(key,value);
    }
    request.send(body);//發送,並配置響應體

    request.onreadystatechange = ()=>{
        if(request.readyState ===4){
            if ( request.status>=200&&request.status<=400){
                successFn.call(undefined,request.responseText);//執行成功函數
            }else if(request.status>=400){
                failFn.call(undefined,request);//執行失敗函數
            }
    }
    }
}

4.1開始封裝

封裝以後的完整代碼

window.jQuery.ajax = ({method,path,body,headers})=>{//ES6語法
   //進行Promise封裝
    return new Promise((resolve,reject)=>{//這句話是套路,記住
        let request = new XMLHttpRequest();
        request.open(method,path);//配置

        for (const key in headers) {//遍歷header,設置響應頭
            let value = headers[key];
            request.setRequestHeader(key,value);
        }
        request.send(body);//發送,並配置響應體

        request.onreadystatechange = ()=>{
            if(request.readyState ===4){
                if ( request.status>=200&&request.status<=400){
                    resolve.call(undefined,request.responseText);//執行成功函數
                }else if(request.status>=400){
                    reject.call(undefined,request);//執行失敗函數
                }
            }
        }
    })
}

return 一個new Promise().
第一個要記住的:這個Promise必須接收一個函數,函數裏面就是要作的事情(即發送請求,Ajax請求),通常來講,把全部東西放在裏面,第一句就是return.而後要作的事情放在裏面.
第二個要記住的:Promise接收的這個函數有兩個參數,一個叫作resolve.一個叫reject
前兩個要記住的寫出來就是

return new Promise((resolve, reject) => {
        //要作的事
    });

第三個要記住的:若是成功了就調一下resolve(),若是失敗了就調用reject(),因此Ajax()參數中不須要successFnfailFn
而且將成功行和失敗行對應的代碼分別改成
resolve.call(undefined,request.responseText);//執行成功函數reject.call(undefined,request);//執行失敗函數

上面是固定的套路
封裝完畢.
只分別修改了這幾行代碼
PyAXOs.png

4.2如何調用

myButton.addEventListener("click",(e)=>{
    //使用ajax
    $.ajax({
        method:"post",
        path:"/xxx",
        body:"username=mtt&password=1",
        headers:{
            "content-type":'application/x-www-form-urlencoded',
            "mataotao":18
        }
    }).then(
        (responseText)=>{console.log(responseText);},//成功就調用這個函數
        (request)=>{console.log(request);}//失敗就調用這個函數
    )
})

ajax()函數後接上.then(),成功就調用then()函數第一個參數裏的函數,失敗就調用then()函數第二個參數裏的函數

簡單的Promise原理:

本身封裝後的Ajax()返回一個new出來的 Promise對象,一個Promise實例,這個Promise實例有一個then屬性,他是一個函數,因此能夠調用then().並且then也會返回一個Promise對象.

Promise接收一個函數,這個函數就是你要作的事情

因此Promise本質上只是規定一種形式!

5 Promise總結

請背下這個代碼

Promise用法

function xxx(){
    return new Promise((f1, f2) => {
        doSomething()
        setTimeout(()=>{
            // 成功就調用 f1,失敗就調用 f2
        },3000)
    })
}

xxx().then(success, fail)

// 鏈式操做
xxx().then(success, fail).then(success, fail)

十五行代碼帶你搞懂Promise - 浪子的文章 -知乎

相關文章
相關標籤/搜索