最近想到了乙個自認為很有意思的面試題如何實現乙個
compose
函式。函式接收數個引數,引數均為
function
型別,右側函式的執行結果將作為左側函式執行的引數來呼叫。
1 compose(arg => `$%`, arg => arg.tofixed(2), arg => arg + 10)(5) //執行結果如上述**,有興趣的同學可以先自己實現一下再來看後續的。15.00%
2 compose(arg => arg.tofixed(2), arg => arg + 10)(5) //
15.00
3 compose(arg => arg + 10)(5) //
15
大致的思路為:
獲取所有的引數
呼叫最後乙個函式,並接收返回值
如果沒有後續的函式,返回資料,如果有,將返回值放入下乙個函式中執行
所以這種情況用遞迴來實現會比較清晰一些
1這樣,我們就實現了上述的function
compose (...funcs)
10 }
compose
函式。
真是可喜可賀,可喜可賀。
本文完。
好了,如果現實生活中開發做需求也是如此爽快不做作就好了,但是,產品總是會來的,需求總是會改的。
我們現在有如下要求,函式需要支援promise
物件,而且要相容普通函式的方式。
示例**如下:
1我們有如下**呼叫,對//為方便閱讀修改的排版
2compose(
3 arg => new promise((resolve, reject) =>
4 settimeout(_ =>
5 resolve(arg.tofixed(2)),
6 10007)
8),9 arg => arg + 10
10 )(5).then(data =>)
tofixed
函式的呼叫新增1000ms
的延遲。讓使用者覺得這個函式執行很慢,方便下次優化
所以,我們就需要去修改compose
函式了。
我們之前的**只能支援普通函式的處理,現在因為新增了promise
物件的原因,所以我們要進行如下修改:
首先,非同步函式改為同步函式是不存在的readfile/readfilesync
這類除外。
所以,最簡單的方式就是,我們將普通函式改為非同步函式,也就是在普通函式外包一層promise
。
1我們針對function
compose (...funcs) )16}
17}1819
//判斷引數是否為`promise`
20function
ispromise (pro)
2324
//將引數轉換為`promise`
25function
promiseify (pro)
compose
**的改動主要是集中在這幾處:
將compose
的返回值改為了promise
物件,這個是必然的,因為內部可能會包含promise
引數,所以我們一定要返回乙個promise
物件
將各個函式執行的返回值包裝為了promise
物件,為了統一返回值。
處理函式返回值,監聽then
和catch
、並將resolve
和reject
傳遞了過去。
現在,我們又得到了乙個新的需求,我們想要在其中某些函式執行中跳過部分**,先執行後續的函式,等到後續函式執行完後,再拿到返回值執行剩餘的**:
1拿到需求後,陷入沉思。。。compose(
2 data => new promise((resolve, reject) => resolve(data + 2.5)),
3 data => new promise((resolve, reject) => resolve(data + 2.5)),
4 async function c (data, next) ,
12 (data, next) => new promise((resolve, reject) =>%`)
16 }).catch(reject) //
先執行後續的**
17}),
18function d (data)
19 )(15).then(console.log) //
0.45%
好好地順序執行**,突然就變成了這個鳥樣,隨時可能會跳到後邊的函式去。
所以我們分析這個新需求的效果:
我們在函式執行到一半時,執行了next
,next
的返回值為後續函式的執行返回值。
也就是說,我們在next
中處理,直接呼叫佇列中的下乙個函式即可;
然後監聽then
和catch
**,即可在當前函式中獲取到返回值;
拿到返回值後就可以執行我們後續的**。
然後他的實現呢,也是非常的簡單,我們只需要修改如下**即可完成操作:
1也就是說,我們會提前執行下乙個函式,而且下乙個函式的//在這裡會強行呼叫`exec`並傳入引數2//
而`exec`的執行,則意味著`funcs`集合中又乙個函式被從佇列中取出來
3 promiseify(func(arg, arg => exec(arg)))
then
事件註冊是在我們當前函式內部的,當我們拿到返回值後,就可以進行後續的處理了。
而我們所有的函式是存放在乙個佇列裡的,在我們提前執行完畢該函式後,後續的執行也就不會再出現了。避免了乙個函式被重複執行的問題。
如果看到這裡已經很明白了,那麼恭喜,你已經了解了實現koajs
最核心的**:
中介軟體的實現方式、洋蔥模型
想必現在整個函式周遭散發著洋蔥
的味道。
koa-compose
1.0,普通函式
2.0,promise函式
3.0,支援洋蔥模型
乙個函式作為另乙個函式的引數
函式的作為變數分裝到另一函式裡面 上面的函式是求乙個定義域能被3正處的數,首先可以想到的是0到100之間內能被3整除的數吧。這個應該很簡單,如下。這裡可以思考的是某個定義域,也就是說上面的i 0和i 100都應該是不確定的值,也就是變數,現在可以定義乙個函式,function checkout st...
乙個openGL的函式
最近挺忙很久沒寫東西。目前在寫一些opengl的東西,對於這個在3年前接觸過但是沒學好的語言一直耿耿於懷,其實很喜歡opengl。而且最近也沒事就一直開始寫著,寫opengl檢視模型的時候其實很重要的乙個東西就是它內部的矩陣棧。所以寫了乙個函式,專門用來輸出日誌,我自己覺的挺好用。這個函式的作用是專...
乙個高ai的分頁函式和乙個url函式
aidu ad 這個分頁 函式非常高只能的 看看就知道了 function ppage total,page,e page 15,e block 10,url color totalpage ceil total e page 頁面數目 p block ceil totalpage e block ...