call a function
call a function backgit
callbackgithub
看這裏:Callback(回調)是什麼?---方應杭知乎ajax
callback 是一種特殊的函數, 這個函數被做爲參數傳給另外一個函數去調用。這樣的函數就是回調函數。
Callback 很常見$button.on('click', function(){})
click後面的 function 就是一個回調,由於「我」沒有調用過這個函數,是 jQuery 在用戶點擊 button 時調用的(當用戶點擊以後,這個函數才執行,如今我只是傳了一個參數,這個參數是一個點擊後要執行的函數)。json
div.addEventListener('click', function(){})
click 後面的 function 也是一個回調,由於「我」沒有調用過這個函數,是瀏覽器在用戶點擊 button 時調用的。segmentfault
通常來講,只要參數是一個函數,那麼這個函數就是回調。promise
請看我寫的封裝的簡易jQuery.ajax()中的successFN
就是一個回調函數.瀏覽器
只有在請求成功並接收到響應的時候纔會執行這個success函數,這就是回調.傳一個函數做爲參數可是不執行,讓另外一個函數去調用,就是回調函數服務器
callback 有一點「反直覺」。
好比說咱們用代碼作一件事情,分爲兩步:step1( ) 和 step2( )。app
符合人類直覺的代碼是:異步
step1()
step2()
callback 的寫法倒是這樣的:
step1(step2)
爲何要這樣寫?或者說在什麼狀況下應該用這個「反直覺」的寫法?
通常(注意我說了通常),在 step1 是一個異步任務的時候,就會使用 callback。
什麼是異步任務呢?
「每日一題」什麼是異步?---方應杭知乎
下一篇博客再詳細記錄吧
若是不使用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 })
$.ajax()
函數會返回一個promise,而後在後面.then(success,fail)
時候,若是成功了就會調用第一個參數裏的函數即success函數,若是失敗了就會調用第二個參數的函數即fail函數.
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
徹底不須要寫函數名
若是你須要對一個結果進行屢次處理,能夠這樣寫:
$.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的結果) }, ()=>{ //第二次處理失敗結果 } )
結果:
看到第二個then裏的函數吧第一次then裏return的結果當作參數,繼續處理.
因此promise的好處是若是想再次用兩個函數,即再次對結果進行處理,就再then 一下,不須要再次取名字了
then的中文含義:而後!
以上就是ajax中promise的簡單使用,那麼如何本身封裝一個呢?
PS:ajax()
函數參數裏的dataType:'json'//預期服務器返回的數據類型,若是不寫,就是響應裏設置的
即:
ajax方法中的dataType:預期服務器返回的數據類型。若是不指定,jQuery 將自動根據 HTTP 包 MIME 信息來智能判斷。
接下來回到咱們本身封裝的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);//執行失敗函數 } } } }
封裝以後的完整代碼
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()
參數中不須要successFn
和failFn
了
而且將成功行和失敗行對應的代碼分別改成resolve.call(undefined,request.responseText);//執行成功函數
和reject.call(undefined,request);//執行失敗函數
上面是固定的套路
封裝完畢.
只分別修改了這幾行代碼
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本質上只是規定一種形式!
請背下這個代碼
Promise用法
function xxx(){ return new Promise((f1, f2) => { doSomething() setTimeout(()=>{ // 成功就調用 f1,失敗就調用 f2 },3000) }) } xxx().then(success, fail) // 鏈式操做 xxx().then(success, fail).then(success, fail)