寫爬蟲時候遇到的批量非同步處理的一些思考和總結。
async/await
是es2017加入的標準,它允許用同步的寫法來進行非同步的操作,它的本質是es6引入的promise
和generator
函式的語法糖。
async
function
sleepy()
/** * @params sleeptime
* @params awaketext
* @params error
* @returns promise*/
function
sleep
(sleeptime, awaketext, error)
else
}, sleeptime);}
);}
通過async
字首定義乙個特殊函式,在函式的內部可以使用await
關鍵字來接乙個promise
型別的值,按照從上到下的順序來執行函式。先通過settimeout
和promise
定義乙個最簡單的非同步函式sleep
。
執行sleepy
函式之後,會按照順序輸出i awake -> and sleep -> awake now
。
前文也說到了async/await
實質上是promise
和generator
的語法糖,上文的sleepy
可以改寫成如下形式:
function
*sleepy()
實際過程中,批量處理非同步請求時常常會遇到與期望不符的情況。我們假設存在複數的請求,我們需要得到這些請求的值。
// sleepy 非同步的請求
const requests =
newarray(10
).fill
(sleepy)
;const results = requests.
map(
async
(request)
=>
await
request()
);// [promise]
上面的例子嘗試將陣列中複數的請求通過map方法返回所有請求的結果來進行批量處理,實際上得到的只能是乙個pending
狀態的promise
陣列。其實我們很容易想到這樣產生的原因,map
等一系列陣列方法是在es5
版本加入的,當時沒有promise
的提案,更沒有async/await
。當時的map
方法應該是直接執行傳入的函式。
// map 的簡單實現
array.prototype.
map=
function
(handler)
return handler;
}
但是既然既然返回的是promise
型別,其實可以很簡單的使用promise.all
的 api 來完成想要操作的結果。
promise.
all(
requests.
map(request =>
request()
)).then
(results =>
);
這樣能夠實現併發多個請求,並在所有請求處理完畢後返回處理結果陣列的需求。而在我自己的爬蟲專案中,需要開啟很多個詳情頁並爬取對應的資料。如果同時併發請求,在資料量大的情況話,可能順時切開上百個詳情頁。此時需要順序完成請求操作。
(
async
function()
})()
;
因為await關鍵字只能在async
函式定義中有效。因此使用iife
來產生async函式環境,達成次序執行的目的。 非同步async await寫法
async await 用asyncio提供的 asyncio.coroutine可以把乙個generator標記為coroutine型別,然後在coroutine內部用yield from呼叫另乙個coroutine實現非同步操作。為了簡化並更好地標識非同步io,從python 3.5開始引入了新...
非同步操作async await
async函式的特點 例 router.get testasync async ctx 1000 const b await 123const c await new promise resolve,reject 2000 ctx.body 看看 的執行過程,它裡面遇到了await,await 表示...
利用 async await 的非同步程式設計
通過使用非同步程式設計,你可以避免效能瓶頸並增強你的應用程式的總體響應能力。從 vs 2012 開始,新引入了乙個簡化的方法,稱為非同步程式設計。我們在 net 4.5 中和 windows 執行時中使用非同步,編譯器它會幫助了我們降低了曾經進行的高難度非同步 編寫的工作,但邏輯結構卻類似於同步 因...