改進 ThinkJS 的非同步程式設計方式

2021-07-03 19:38:48 字數 3537 閱讀 7817

thinkjs 是奇舞團開源的一款 node mvc 框架,主要由 welefen 開發。簡單介紹一下:

thinkjs 是乙個快速、簡單的基於 mvc 和物件導向的輕量級 node.js 開發框架,遵循 mit 協議發布。秉承簡潔易用的設計原則,在保持出色的效能和至簡的**同時,注重開發體驗和易用性,為 web 應用開發提供強有力的支援。

thinkjs 借鑑了很多 thinkphp 的特性,同時結合 node.js 的特性,使用了 es6 promise,讓非同步程式設計更加簡單、方便。via

我是 thinkjs 的第一批使用者,大約在 2014 年初,我把我的部落格程式用 thinkjs 重新實現了一遍,前後花了不到一周。之後的這一年多,我用 thinkjs 寫過大大小小很多個系統和工具,越用越覺得好用,現在已經完全離不開了。

今天這篇部落格我準備聊聊 thinkjs 中的非同步程式設計方式以及我採用的方案。

前面介紹中提到過,thinkjs 是基於 promise 實現的非同步程式設計。我之前寫的那篇「非同步程式設計:when.js 快速上手」已經比較詳細的介紹了 promise 相關知識。直接看一段摘自於我部落格程式的**:

jsindexaction : function

());

}

這段**中getpostlist是乙個查詢資料庫的非同步操作,它的返回值在then中才可以拿到。如果then中還有其他非同步操作,最後還是會導致巢狀很深。這段**還會遇到經典的this指標問題,需要賦值儲存或者用bind解決。這段**能不能實現得更優雅一點呢?我們先來看另一段:

jsasync function

myfunction

()

這樣寫非同步邏輯,是不是很讚?既好看又好懂,也沒有this指標問題。實際上,這是 es7 裡的async function,還得等一陣子才能用。

之前我在介紹 es6 的生成器函式(generator function)時,曾經舉過乙個生成器函式結合 promise 使用的例子,下面摘錄一段(全文在這裡):

jsvar all = q.async(function* ()

);

有沒發現這段**跟上面的async function非常像?沒錯!利用生成器函式和 q 框架,可以方便地把 promise 巢狀變成平級,這一切現在就能用!

在繼續之前,請通過node -v檢查下 node 版本,推薦公升級到最新的 0.12。對於 ubuntu 系統,可以這樣安裝最新的 0.12:

shellcurl -sl  | sudo bash -

sudo apt-get install -y nodejs

有了最新的 node,在使用 node 命令時,還需要帶上--harmony引數,例如啟動 thinkjs:

node --harmony www/index.js
如果用 pm2 啟動程式,也需要帶上這個引數,例如:

pm2 start ~/www/blog/www/index.js -n blog --node-args="--harmony"
安裝並引入 q 模組之後,就可以開始改造本文第一段**了:

jsindexaction : q.async(function* ()

)

這下,**是不是更清晰明了。改動不大,但效果很明顯,上面提出的問題都解決了。

這裡有個小點需要注意下:如果你使用了 thinkjs 的 action 引數自動繫結功能,例如這樣:

jstagaction : function

(tag)

);}

改造之後,需要通過this.get('tag')獲取引數值:

jstagaction : q.async(function* ()

)

因為 thinkjs 的引數自動繫結依賴function.tostring,應該沒匹配生成器函式格式。當然下面這樣寫也可以,只是更複雜:

jstagaction : function

(tag)

.bind(this));

}

q.asyncq.spawn的文件在這裡可以找到。主要區別是q.async返回等待執行的函式;q.spawn會立即執行。

最後放上一大段**結束本文,這是我的部落格詳情頁實現**:

jspostaction : q.async(function* ()

//未公開的文章,非登入使用者訪問時重定向到首頁

if(post.status != 'publish')

}//如果有 slug,但是用 id 訪問,301 到更友好的 url

var slug = post.slug;

if(slug && slug != slugorid)

var data = {};

var prevpost = post.getprevpost(post.pub_date);

var nextpost = post.getnextpost(post.pub_date);

var morepost = yield

promise.all([prevpost, nextpost]);

data.prevpost = isempty(morepost[0]) ? false : morepost[0];

data.nextpost = isempty(morepost[1]) ? false : morepost[1];

//獲取 toc

var gettocresult = thinkrequire('tocapi')(post.content);

post.content = gettocresult[0];

data.toc = gettocresult[1];

data.tocname = '文章目錄';

data.currentpage = 'post-' + (post.slug || post.id);

data.title = post.title + ' | ';

data.post = post;

this.assign(data);

this.display('blog/theme/' + theme + '/single_post.html');

})

注:後來我又把 q 換成了 bluebird,bluebird 的 promise.coroutine 和q.async功能一樣,直接替換即可。

--eof--

JS的非同步程式設計

generator非同步方案 async await語法糖 let url1 url1 url2 url2 ajax function getdata url,data error function err let url1 url1 url2 url2 getdata url1 then res ...

利用 async await 的非同步程式設計

通過使用非同步程式設計,你可以避免效能瓶頸並增強你的應用程式的總體響應能力。從 vs 2012 開始,新引入了乙個簡化的方法,稱為非同步程式設計。我們在 net 4.5 中和 windows 執行時中使用非同步,編譯器它會幫助了我們降低了曾經進行的高難度非同步 編寫的工作,但邏輯結構卻類似於同步 因...

nodeJS中的非同步程式設計

nodejs 不是單執行緒 在部落格專案中關於非同步問題 1.當使用者新增一條部落格時 需要通過post方式向伺服器傳送資料 後台獲取使用者以post方式拿到傳送過來的資料 然後存入資料庫 上面的 建立乙個空字串 當使用者向伺服器傳送請求時出發data事件將依次獲取來資料進行拼接 當使用者請求結束後...