摘要:回調(diào)使用封裝入門回調(diào)是啥看這里回調(diào)是什么方應(yīng)杭知乎是一種特殊的函數(shù),這個(gè)函數(shù)被作為參數(shù)傳給另一個(gè)函數(shù)去調(diào)用。
回調(diào)、使用Promise封裝ajax()、Promise入門 1 回調(diào)是啥
call a function
call a function back
callback
看這里:Callback(回調(diào))是什么?---方應(yīng)杭知乎
callback 是一種特殊的函數(shù),這個(gè)函數(shù)被作為參數(shù)傳給另一個(gè)函數(shù)去調(diào)用。這樣的函數(shù)就是回調(diào)函數(shù)。1.1 回調(diào)例子
Callback 很常見
$button.on("click", function(){})
click后面的 function 就是一個(gè)回調(diào),因?yàn)椤肝摇箾]有調(diào)用過這個(gè)函數(shù),是 jQuery 在用戶點(diǎn)擊 button 時(shí)調(diào)用的(當(dāng)用戶點(diǎn)擊之后,這個(gè)函數(shù)才執(zhí)行,現(xiàn)在我只是傳了一個(gè)參數(shù),這個(gè)參數(shù)是一個(gè)點(diǎn)擊后要執(zhí)行的函數(shù))。
div.addEventListener("click", function(){})
click 后面的 function 也是一個(gè)回調(diào),因?yàn)椤肝摇箾]有調(diào)用過這個(gè)函數(shù),是瀏覽器在用戶點(diǎn)擊 button 時(shí)調(diào)用的。
一般來說,只要參數(shù)是一個(gè)函數(shù),那么這個(gè)函數(shù)就是回調(diào)。
請看我寫的封裝的簡易jQuery.ajax()中的successFN就是一個(gè)回調(diào)函數(shù).
只有在請求成功并接收到響應(yīng)的時(shí)候才會執(zhí)行這個(gè)success函數(shù),這就是回調(diào).傳一個(gè)函數(shù)作為參數(shù)但是不執(zhí)行,讓另一個(gè)函數(shù)去調(diào)用,就是回調(diào)函數(shù)
1.2Callback 有點(diǎn)反直覺callback 有一點(diǎn)「反直覺」。
比如說我們用代碼做一件事情,分為兩步:step1( ) 和 step2( )。
符合人類直覺的代碼是:
step1()
step2()
callback 的寫法卻是這樣的:
step1(step2)
為什么要這樣寫?或者說在什么情況下應(yīng)該用這個(gè)「反直覺」的寫法?
一般(注意我說了一般),在 step1 是一個(gè)異步任務(wù)的時(shí)候,就會使用 callback。
什么是異步任務(wù)呢?
2.什么是異步?「每日一題」什么是異步?---方應(yīng)杭知乎
下一篇博客再詳細(xì)記錄吧
「每日一題」Promise 是什么?
代碼都在這里
3.1 $.Ajax()中的promise如果不使用promise,$.ajax請求的時(shí)候成功和失敗的回調(diào)函數(shù)是寫在參數(shù)里的,他是對象參數(shù)的一個(gè)值
$.ajax({ method:"post", url:"/xxx", data:"username=mtt&password=1", dataType:"json", success:()=>{}//成功后的回調(diào)函數(shù) error:()=>{}//失敗后的回調(diào)函數(shù) } )
如果使用jQuery.axja()發(fā)送請求,并使用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"http://預(yù)期服務(wù)器返回的數(shù)據(jù)類型,如果不寫,就是響應(yīng)里設(shè)置的 } ).then(success,fail)//$.ajax()返回一個(gè)promise })
成功的結(jié)果:
換一個(gè)不存在的地址/mtt失敗的結(jié)果
$.ajax()函數(shù)會返回一個(gè)promise,然后在后面.then(success,fail)時(shí)候,如果成功了就會調(diào)用第一個(gè)參數(shù)里的函數(shù)即success函數(shù),如果失敗了就會調(diào)用第二個(gè)參數(shù)的函數(shù)即fail函數(shù).
3.1.1 promise的第一個(gè)意義promise的第一個(gè)意義:不用記住成功和失敗到底是success,還是successFN或者是fail或者是error,不用記住函數(shù)名字.只需要知道成功是第一個(gè)參數(shù),失敗時(shí)第二個(gè)參數(shù),比如這樣寫
//使用ajax $.ajax({ method:"post", url:"/xxx", data:"username=mtt&password=1", dataType:"json"http://預(yù)期服務(wù)器返回的數(shù)據(jù)類型,如果不寫,就是響應(yīng)里設(shè)置的 } ).then((responseText)=>{console.log(responseText)},()=>{console.log("失敗")})//$.ajax()返回一個(gè)promise
完全不需要寫函數(shù)名
3.1.2promise的第二個(gè)意義如果你需要對一個(gè)結(jié)果進(jìn)行多次處理,可以這樣寫:
$.ajax({ method:"post", url:"/xxx", data:"username=mtt&password=1", dataType:"json"http://預(yù)期服務(wù)器返回的數(shù)據(jù)類型,如果不寫,就是響應(yīng)里設(shè)置的 } ).then((responseText)=>{ console.log(responseText) return responseText;//如果要對結(jié)果進(jìn)行多次處理,就在這里return,第二次then就會得到這個(gè)return的數(shù)據(jù) },()=>{ console.log("失敗") }).then(//開始第二次then (上一次return的結(jié)果)=>{ console.log("第二次處理") console.log(上一次return的結(jié)果) }, ()=>{ //第二次處理失敗結(jié)果 } )
結(jié)果:
看到第二個(gè)then里的函數(shù)吧第一次then里return的結(jié)果當(dāng)做參數(shù),繼續(xù)處理.
所以promise的好處是如果想再次用兩個(gè)函數(shù),即再次對結(jié)果進(jìn)行處理,就再then 一下,不需要再次取名字了
then的中文含義:然后!
以上就是ajax中promise的簡單使用,那么如何自己封裝一個(gè)呢?
PS:ajax()函數(shù)參數(shù)里的dataType:"json"http://預(yù)期服務(wù)器返回的數(shù)據(jù)類型,如果不寫,就是響應(yīng)里設(shè)置的 即:4封裝一個(gè)類似$.Ajax()中的Promise的簡易版本(皮毛,以后深入)
ajax方法中的dataType:預(yù)期服務(wù)器返回的數(shù)據(jù)類型。如果不指定,jQuery 將自動根據(jù) HTTP 包 MIME 信息來智能判斷。
接下來回到我們自己封裝的jQuery.Ajax()代碼.我們以此為基礎(chǔ)繼續(xù)來封裝promise
以前封裝的代碼在這里
也可以看我前一篇博客,里面有如何封裝Ajax()的方法和詳細(xì)過程.
原來的封裝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,設(shè)置響應(yīng)頭 let value = headers[key]; request.setRequestHeader(key,value); } request.send(body);//發(fā)送,并配置響應(yīng)體 request.onreadystatechange = ()=>{ if(request.readyState ===4){ if ( request.status>=200&&request.status<=400){ successFn.call(undefined,request.responseText);//執(zhí)行成功函數(shù) }else if(request.status>=400){ failFn.call(undefined,request);//執(zhí)行失敗函數(shù) } } } }4.1開始封裝
封裝之后的完整代碼
window.jQuery.ajax = ({method,path,body,headers})=>{//ES6語法 //進(jìn)行Promise封裝 return new Promise((resolve,reject)=>{//這句話是套路,記住 let request = new XMLHttpRequest(); request.open(method,path);//配置 for (const key in headers) {//遍歷header,設(shè)置響應(yīng)頭 let value = headers[key]; request.setRequestHeader(key,value); } request.send(body);//發(fā)送,并配置響應(yīng)體 request.onreadystatechange = ()=>{ if(request.readyState ===4){ if ( request.status>=200&&request.status<=400){ resolve.call(undefined,request.responseText);//執(zhí)行成功函數(shù) }else if(request.status>=400){ reject.call(undefined,request);//執(zhí)行失敗函數(shù) } } } }) }
return 一個(gè)new Promise().
第一個(gè)要記住的:這個(gè)Promise必須接收一個(gè)函數(shù),函數(shù)里面就是要做的事情(即發(fā)送請求,Ajax請求),一般來說,把所有東西放在里面,第一句就是return.然后要做的事情放在里面.
第二個(gè)要記住的:Promise接收的這個(gè)函數(shù)有兩個(gè)參數(shù),一個(gè)叫做resolve.一個(gè)叫reject
前兩個(gè)要記住的寫出來就是
return new Promise((resolve, reject) => { //要做的事 });
第三個(gè)要記住的:如果成功了就調(diào)一下resolve(),如果失敗了就調(diào)用reject(),所以Ajax()參數(shù)中不需要successFn和failFn了
并且將成功行和失敗行對應(yīng)的代碼分別改為
resolve.call(undefined,request.responseText);//執(zhí)行成功函數(shù)和reject.call(undefined,request);//執(zhí)行失敗函數(shù)
上面是固定的套路
封裝完畢.
只分別修改了這幾行代碼
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);},//成功就調(diào)用這個(gè)函數(shù) (request)=>{console.log(request);}//失敗就調(diào)用這個(gè)函數(shù) ) })
在ajax()函數(shù)后接上.then(),成功就調(diào)用then()函數(shù)第一個(gè)參數(shù)里的函數(shù),失敗就調(diào)用then()函數(shù)第二個(gè)參數(shù)里的函數(shù)
簡單的Promise原理:
自己封裝后的Ajax()返回一個(gè)new出來的 Promise對象,一個(gè)Promise實(shí)例,這個(gè)Promise實(shí)例有一個(gè)then屬性,他是一個(gè)函數(shù),所以可以調(diào)用then().而且then也會返回一個(gè)Promise對象.
Promise接收一個(gè)函數(shù),這個(gè)函數(shù)就是你要做的事情
所以Promise本質(zhì)上只是規(guī)定一種形式!
5 Promise總結(jié)請背下這個(gè)代碼
Promise用法
function xxx(){ return new Promise((f1, f2) => { doSomething() setTimeout(()=>{ // 成功就調(diào)用 f1,失敗就調(diào)用 f2 },3000) }) } xxx().then(success, fail) // 鏈?zhǔn)讲僮?xxx().then(success, fail).then(success, fail)
十五行代碼帶你搞懂Promise - 浪子的文章 -知乎
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96734.html
摘要:而真正的回調(diào)函數(shù),是在的外面被調(diào)用的,也就是和中調(diào)用方法返回的是一個(gè)新的實(shí)例注意,不是原來那個(gè)實(shí)例。 前端開發(fā)中經(jīng)常會進(jìn)行一些異步操作,常見的異步有: 網(wǎng)絡(luò)請求:ajax IO操作: readFile 定時(shí)器:setTimeout 博客地址 回調(diào) 最基礎(chǔ)的異步解決方案莫過于回調(diào)函數(shù)了 前端經(jīng)常會在成功時(shí)和失敗時(shí)分別注冊回調(diào)函數(shù) const req = new XMLHttpRequ...
摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:回調(diào)函數(shù)這是最原始的一種異步解決方法。從的對象演化而來對象是提出的一種對異步編程的解決方案,但它不是新的語法,而是一種新的寫法,允許將回調(diào)函數(shù)的嵌套改成鏈?zhǔn)秸{(diào)用。 一、前言 異步編程對JavaScript來說非常重要,因?yàn)镴avaScript的語言環(huán)境是單線程的,如果沒有異步編程將變得非常可怕,估計(jì)根本無法使用。這篇文章就來總結(jié)一下從最原始的回調(diào)函數(shù)到現(xiàn)在的ES6、ES7的新方法。 文...
摘要:有了對象,就可以將異步操作以同步操作的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù)。此外,對象提供統(tǒng)一的接口,使得控制異步操作更加容易。它的作用是為實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)。這時(shí),第二個(gè)方法指定的回調(diào)函數(shù),就會等待這個(gè)新的對象狀態(tài)發(fā)生變化。 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù)和事件)更合理和更強(qiáng)大。它由社區(qū)最早出和實(shí)現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了...
閱讀 1166·2023-04-25 17:28
閱讀 3617·2021-10-14 09:43
閱讀 3978·2021-10-09 10:02
閱讀 1951·2019-08-30 14:04
閱讀 3142·2019-08-30 13:09
閱讀 3280·2019-08-30 12:53
閱讀 2907·2019-08-29 17:11
閱讀 1833·2019-08-29 16:58