我在coffeescript中写了一个缓存加温工具。我们有2个目标服务器,5个站点,每个站点1000个页面,每页3个版本。所以总共有30k的请求。我正在使用async.each
,async.eachLimit
和async.eachSeries
,而且效果很好。但是,代码变得有点难以阅读。我看过async.waterfall
并承诺,但这看起来不会有所帮助。
work = () ->
async.each config.targets, (target, callback) ->
async.eachLimit sitemaps, config.concurrency.sitemaps, (sitemap, callback) ->
async.eachLimit sitemap, config.concurrency.urls, (url, callback) ->
async.eachSeries config.requests, (req, callback) ->
doRequest target, sitemap, url, req, callback
, callback
, callback
, callback
, (err) ->
console.log "All done"
我有什么办法可以重做吗?
如果参数顺序为async.each array, callback, iterator
,我会对上面的布局感到满意。但回调的语法有点难以阅读。
答案 0 :(得分:0)
如何将函数定义拆分为自己的行?我还添加了括号,使函数调用更清晰(对我而言)。
work = () ->
async.each( config.targets, (target, callback) ->
async.eachLimit( sitemaps, config.concurrency.sitemaps,
(sitemap, callback) ->
async.eachLimit( sitemap, config.concurrency.urls,
(url, callback) ->
async.eachSeries( config.requests,
(req, callback) ->
doRequest( target, sitemap, url, req, callback)
, callback)
, callback)
, callback)
, (err) ->
console.log "All done"
)
修改
理论上,一个或多个内部循环可以作为命名函数分解。例如:
foo1 = (sitemap, callback) ->
async.eachLimit( sitemap, config.concurrency.urls,
(url, callback) ->
async.eachSeries( config.requests,
(req, callback) ->
doRequest( target, sitemap, url, req, callback)
, callback)
, callback)
work1 = () ->
async.each( config.targets, (target, callback) ->
async.eachLimit( sitemaps, config.concurrency.sitemaps,
foo1
, callback)
, (err) ->
console.log "All done"
)
# error - target is not defined in doRequest(target...)
此处的问题是,target
循环设置的work1
不会通过foo1
传递给doRequest
。
看起来async.apply
可以用来解决这个问题
foo2 = (target, sitemap, callback) ->
async.eachLimit( sitemap, config.concurrency.urls,
(url, callback) ->
async.eachSeries( config.requests,
(req, callback) ->
doRequest( target, sitemap, url, req, callback)
, callback)
, callback)
work2 = () ->
async.each( config.targets, (target, callback) ->
async.eachLimit( sitemaps, config.concurrency.sitemaps,
async.apply(foo2, target)
, callback)
, (err) ->
console.log "All done 2"
)
或者将这种分区推向极致:
foo1 = (target, callback) ->
async.eachLimit( sitemaps, config.concurrency.sitemaps
, async.apply(foo2, target)
, callback)
foo2 = (target, sitemap, callback) ->
async.eachLimit( sitemap, config.concurrency.urls
, async.apply(foo3, target, sitemap)
, callback)
foo3 = (target, sitemap, url, callback) ->
async.eachSeries( config.requests
, async.apply(doRequest, target, sitemap, url)
, callback)
work3 = () ->
async.each(config.targets, foo1
, (err) ->
console.log "All done 3"
)
其他绑定/部分方法可行
foo2.bind(null, target) # Javascript bind
_.partial(foo2, target) # lodash, underscore