LazyMan问题与解法

http://mp.weixin.qq.com/s/drNGvLZddQztcUzSh8OsSw

给出了一道题目,并给出了解法:

题目:

实现一个LazyMan,可以按照以下方式调用:

LazyMan(“Hank”)输出:

Hi! This is Hank!

LazyMan(“Hank”).sleep(10).eat(“dinner”)输出

Hi! This is Hank!

//等待10秒..

Wake up after 10

Eat dinner~

LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出

Hi This is Hank!

Eat dinner~

Eat supper~

LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出

//等待5秒

Wake up after 5

Hi This is Hank!

Eat supper

以此类推。

这是典型的JavaScript流程控制,问题的关键是如何实现任务的顺序执行。在Express有一个类似的东西叫中间件,这个中间件和我们这里的吃饭、睡觉等任务很类似,每一个中间件执行完成后会调用next()函数,这个函数用来调用下一个中间件。

对于这个问题,我们也可以利用相似的思路来解决,首先创建一个任务队列,然后利用next()函数来控制任务的顺序执行:

    function _LazyMan(name) {

        this.tasks = [];  

        var self = this;

        var fn =(function(n){

            var name = n;

            return function(){

                console.log("Hi! This is " + name + "!");

                self.next();

            }

        })(name);

        this.tasks.push(fn);

        setTimeout(function(){

            self.next();

        }, 0); // 在下一个事件循环启动任务

    }

    /* 事件调度函数 */

    _LazyMan.prototype.next = function() {

        var fn = this.tasks.shift();

        fn && fn();

    }

    _LazyMan.prototype.eat = function(name) {

        var self = this;

        var fn =(function(name){

            return function(){

                console.log("Eat " + name + "~");

                self.next()

            }

        })(name);

        this.tasks.push(fn);

        return this; // 实现链式调用

    }

    _LazyMan.prototype.sleep = function(time) {

        var self = this;

        var fn = (function(time){

            return function() {

                setTimeout(function(){

                    console.log("Wake up after " + time + "s!");

                    self.next();

                }, time * 1000);

            }

        })(time);

        this.tasks.push(fn);

       return this;

    }

    _LazyMan.prototype.sleepFirst = function(time) {

        var self = this;

        var fn = (function(time) {

            return function() {

                setTimeout(function() {

                    console.log("Wake up after " + time + "s!");

                    self.next();

                }, time * 1000);

            }

        })(time);

        this.tasks.unshift(fn);

        return this;

    }

    /* 封装 */

    function LazyMan(name){

        return new _LazyMan(name);

    }

Express中间件

http://www.expressjs.com.cn/guide/using-middleware.html

Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。

中间件(Middleware) 是一个函数,它可以访问请求对象(request object (req)), 响应对象(response object (res)), 和 web 应用中处于请求-响应循环流程中的中间件,一般被命名为 next 的变量。

中间件的功能包括:

  • 执行任何代码。
  • 修改请求和响应对象。
  • 终结请求-响应循环。
  • 调用堆栈中的下一个中间件。

如果当前中间件没有终结请求-响应循环,则必须调用 next() 方法将控制权交给下一个中间件,否则请求就会挂起。

Express 应用可使用如下几种中间件:

使用可选则挂载路径,可在应用级别或路由级别装载中间件。另外,你还可以同时装在一系列中间件函数,从而在一个挂载点上创建一个子中间件栈。

应用级中间件

应用级中间件绑定到 app 对象 使用 app.use()app.METHOD(), 其中, METHOD 是需要处理的 HTTP 请求的方法,例如 GET, PUT, POST 等等,全部小写。例如:

var app = express();

// 没有挂载路径的中间件,应用的每个请求都会执行该中间件
app.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
}); // 挂载至 /user/:id 的中间件,任何指向 /user/:id 的请求都会执行它
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
}); // 路由和句柄函数(中间件系统),处理指向 /user/:id 的 GET 请求
app.get('/user/:id', function (req, res, next) {
res.send('USER');
}); 下面这个例子展示了在一个挂载点装载一组中间件。 // 一个中间件栈,对任何指向 /user/:id 的 HTTP 请求打印出相关信息
app.use('/user/:id', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});

lua APITools middleware

https://docs.apitools.com/docs/middleware/index.html#lua-api-docs

We've seen how to proxy HTTP(s) requests through APItools and now we're going to add a whole new layer: applying transformations both to the HTTP(s) requests and responses. You can do that with middleware, small snippets of lua code that will control the transactions in different points of the process.

Middleware can be helpful for many different things, as for example:

- Creating alerts and other types of notifications
- Fixtures
- Transforming data formats on the fly
- Avoiding rate limits
- Authenticating apps with any API
- ... you name it!

They also come in handy, for example, when getting started with a new API because you can quickly see what others are using a given API for and get your hands on it their middleware.

https://github.com/APItools/middleware/tree/master/middleware

例如 404 alert 中间件

return function (request, next_middleware)
local five_mins = *
local res = next_middleware()
local last_mail = bucket.middleware.get('last_mail')
if res.status == and (not last_mail or last_mail < time.now() - five_mins) then
send.mail('YOUR-MAIL-HERE@gmail.com', "A 404 has ocurred",
"a 404 error happened in " .. request.uri_full .. ' see full trace: ' .. trace.link)
bucket.middleware.set('last_mail', time.now())
end
return res
end

CORS中间件

return function (request, next_middleware)
local res = next_middleware()
-- Allow origin from certain domains (change as required)
res.headers['Access-Control-Allow-Origin'] = "http://domain1.com http://domain2.com"
-- Anable all domains (uncomment and comment the previous one if required)
-- res.headers['Access-Control-Allow-Origin'] = "*"
return res
end

图片Lazy加载技术:

http://code.ciaoca.com/jquery/lazyload/

基于 jQuery 的图片延迟加载插件,在用户滚动页面到图片之后才进行加载。

对于有较多的图片的网页,使用图片延迟加载,能有效的提高页面加载速度。

载入 JavaScript 文件

<script src="jquery.js"></script>
<script src="jquery.lazyload.js"></script> 修改 HTML 代码中需要延迟加载的 IMG 标签 <!--
将真实图片地址写在 data-original 属性中,而 src 属性中的图片换成占位符的图片(例如 1x1 像素的灰色图片或者 loading 的 gif 图片)
添加 class="lazy" 用于区别哪些图片需要延时加载,当然你也可以换成别的关键词,修改的同时记得修改调用时的 jQuery 选择器
添加 width 和 height 属性有助于在图片未加载时占满所需要的空间
-->
<img class="lazy" src="grey.gif" data-original="example.jpg" width="640" heigh="480"> 调用 Lazy Load $('img.lazy').lazyload();

Lazy evaluation技术

http://www.cnblogs.com/Wayou/p/lazy-evaluation.html

延迟求值带来的另一个好处是延迟执行。无论何时你写了段链式代码,只有在显式地调用了.value()后才会真正执行。这样一来,在数据源需要异步去拉取的情况下,可以保证我们处理的是最新的数据。

var wallet = _(assets).filter(ownedBy('me'))
.pluck('value')
.reduce(sum); $json.get("/new/assets").success(function(data) {
assets.push.apply(assets, data); // 更新数据源
wallet.value(); // 返回的结果是最新的
});

而且这种机制在某些情况下也会提高执行效果。我们可以老早发送一个请求获取数据,然后指定一个精确的时间来执行。

http://danieltao.com/lazy.js/

Asynchronous iteration

You've probably seen code snippets before that show how to iterate over an array asynchronously in JavaScript. But have you seen an example packed full of map-y, filter-y goodness like this?
var asyncSequence = Lazy(array)
.async(100) // specifies a 100-millisecond interval between each element
.map(inc)
.filter(isEven)
.take(20); // This function returns immediately and begins iterating over the sequence asynchronously.
asyncSequence.each(function(e) {
console.log(new Date().getMilliseconds() + ": " + e);
}); function inc(x) { return x + 1; }
function isEven(x) { return x % 2 === 0; }

Python Lazy Evaluation

https://en.wikipedia.org/wiki/Lazy_evaluation

The benefits of lazy evaluation include:

  • The ability to define control flow (structures) as abstractions instead of primitives.
  • The ability to define potentially infinite data structures. This allows for more straightforward implementation of some algorithms.
  • Performance increases by avoiding needless calculations, and error conditions in evaluating compound expressions.

In Python 3.x the range() function[18] returns a special range object which computes elements of the list on demand. Elements of the range object are only generated when they are needed (e.g., when print(r[3]) is evaluated in the following example), so this is an example of lazy or deferred evaluation:

 >>> r = range(10)
>>> print(r)
range(0, 10)
>>> print(r[3])
3
This change to lazy evaluation saves execution time for large ranges which may never be fully referenced and memory usage for large ranges where only one or a few elements are needed at any time.

其它实现Lazy问题的思路

本题中, Lazy问题是借助 原生js语法实现, 可在浏览器端执行。

如果不考虑兼容性, 还可以考虑一下实现方法:

1、 使用reactJS实现, 控制流。

2、 Promise

3、 async 和 await

由LazyMan联想到的的更多相关文章

  1. 重看Decorator Pattern,联想到Delegate传递及Flags Enum--欢迎拍砖!

    话说装饰模式(Decorator)的动机是“动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活.[GOF <设计模式>]”.再次学到该模式,有感 ...

  2. Codeforces Round #263 (Div. 2)C(贪心,联想到huffman算法)

    数学家伯利亚在<怎样解题>里说过的解题步骤第二步就是迅速想到与该题有关的原型题.(积累的重要性!) 对于这道题,可以发现其实和huffman算法的思想很相似(可能出题人就是照着改编的).当 ...

  3. 从new Function创建函数联想到MVC模式

    我们知道任何一个自定义函数都是Function构造器的实例,所以我们可以通过new Function的方式来创建函数,使用语法很简单, new Function(形参1, 形参2, ..., 形参N, ...

  4. [Mysql]由Data truncated for column联想到的sql_mode配置

    系统日志中出现了 ata truncated for column 'agent' at row 1 mysql出现这个问题的原因,无非就是字符集设置 或者是 字段过长导致的. mysql在初始化的时 ...

  5. 从循环里面用QPixmap new对象很耗时联想到的

    1.在循环里面用QPixmap new图片对象延迟很高,这个是通过打时间日志得出的,深层原因还不清楚: 2.自制的图片浏览器在初始化的时候会初始化自己的一个图片列表,所以要用到上面的描述.所有图片的初 ...

  6. 一次Socket通信联想到的Zookeeper源码实现

    最近做一个短信平台,要接入短信网关平台,网关平台使用C,短信平台属于公司内部对外应用,使用Java开发,两边通信采用TCP/IP协议

  7. 击鼓传花联想到了Java设计模式:责任链模式

    目录 应用场景 简单示例 责任链模式 定义 意图 主要解决问题 何时使用 优缺点 击鼓传花的故事 应用场景 http web请求处理,请求过来后将经过转码.解析.参数封装.鉴权等一系列的处理(责任), ...

  8. 读书笔记 effective c++ Item 30 理解内联的里里外外 (大师入场啦)

    最近北京房价蹭蹭猛涨,买了房子的人心花怒放,没买的人心惊肉跳,咬牙切齿,楼主作为北漂无房一族,着实又亚历山大了一把,这些天晚上睡觉总是很难入睡,即使入睡,也是浮梦连篇,即使亚历山大,对C++的热情和追 ...

  9. 题解 loj3050 「十二省联考 2019」骗分过样例

    CASE \(1\sim 3\) \(n\)组测试数据,每次输入一个数\(x\),求\(19^x\). 测试点\(1\),\(x=0,1,\dots n-1\),可以直接递推. 测试点\(2\)要开l ...

随机推荐

  1. [Unity3D]Unity资料大全免费分享

     都是网上找的连七八糟的资料了,整理好分享的,有学习资料,视频,源码,插件……等等 东西比较多,不是所有的都是你需要的,可以按  ctrl+F 来搜索你要的东西,如果有广告,不用理会,关掉就可以了,如 ...

  2. iOS 单例模式范例

    The singleton pattern is useful for creating objects that are shared across the entire application, ...

  3. BZOJ4712 : 洪水

    首先不难列出DP方程: $dp[x]=\min(w[x],h[x])$ $h[x]=\sum dp[son]$ 当$w[x]$增加时,显然$dp[x]$不会减少,那么我们求出$dp[x]$的增量$de ...

  4. 最新版 CocoaPods 的安装流程

                                       iOS 最新版 CocoaPods 的安装流程     1.移除现有Ruby默认源 $gem sources --remove h ...

  5. BOM,文档宽高及窗口事件小析

    (一)BOM:Browser Object Model(浏览器对象模型)页面上所有的变量都是window的属性 一.方法:1. open(,)打开一个新窗口(页面)一参为页面地址url,二参为打开方式 ...

  6. 李洪强iOS经典面试题139-Swift

    李洪强iOS经典面试题139-Swift Swift 网上有很多Swift的语法题,但是Swift现在语法还未稳定,所以在这里暂时不贴出语法题,可以自行搜索. Swift和Objective-C的联系 ...

  7. List集合特有的迭代器 ListIterator

  8. python的编码规范【摘】

    模块名:小写字母,单词之间用_分割ad_stats.py 包名:和模块名一样 类名:单词首字母大写AdStatsConfigUtil 全局变量名(类变量,在java中相当于static变量):大写字母 ...

  9. 【iCore3应用开发平台】发布 iCore3 应用开发平台PID控制代码

    说明:1.本代码包包含FPGA和STM32F407两部分内容2.FPGA工程为出厂代码FPGA工程,版本为REV43.STM32F407为只含PID控制的ARM工程4.在使用风扇过程中,请勿将手伸入扇 ...

  10. centos6.5新增加硬盘挂载并实现开机时自动挂载

    在内网主机新增一个2T硬盘,先关机断电再连接硬盘数据线和电源线! 查看当前磁盘设备信息: [root@tb ~]# fdisk -lWARNING: GPT (GUID Partition Table ...