澳门新萄京:NodeJs中的非拥塞方法介绍,码农终
分类:服务器

唯独,那七个函数是异步的,在计时的进度中它们背后的代码依然会继续施行。这就本人来写个sleep()函数吧,互连网也流传了有的达成方式,不过作者意识上面这几个法子简便易懂况且实用,所以在这里处享受给我们:

安装进程就背着了。若是成功是能使用node的下令。node.js调节和测量试验是老大有益的。每一个后台语言都有三个向十一分黑黢黢的主宰台团输出语用的通令。node.js沿用FF这套东西,也便是console对象与其方法。大家率先建贰个example.js文件,内容如下,然后在调节台张开它。 复制代码 代码如下: console.log for{ console.log } node example.js。 你相对不要在node.js使用alert进行调护医疗,那是浏览器带的大局方法,不报错才怪。 输出结果如下: 复制代码 代码如下: var log = function () { process.stdout.write(format.apply 'n'); } var info = function () { process.stdout.write(format.apply 'n'); } var warn = function () { writeError(format.apply 'n'); } var error = function () { writeError(format.apply 'n'); } var dir = function { var util = require; process.stdout.write 'n'); } var time = function { times[label] = Date.now(); } var timeEnd = function { var duration = Date.now() - times[label]; exports.log('undefined: NaNms', label, duration); } var trace = function { // TODO probably can to do this better with V8's debug object once that is // exposed. var err = new Error; err.name = 'Trace'; err.message = label || ''; Error.captureStackTrace(err, arguments.callee); console.error; } var assert = function { if { var arr = Array.prototype.slice.call; require.ok(false, format.apply; } } 通过那几个函数,大家大概明白到node.js在全局功能域增多了些什么,如require, process。但也不能够武断说是,因为它们只怕是有些功用域的村办对象。不过,领会这个全局对象,并从那一个指标上起身去询问别的对象,特别常有扶助大家了然node.js的生态结构。在前边三个,每当浏览器晋级,作者就遍历一下window对象以致其个成分节点就摸清它又扩张了何等方法与脾气,然后再查文书档案。这一个更新日志不恐怕把整个细节都告诉你的,必得本身入手遍历一下,那样您就比外人知道得越多。好了,大家去找node.js的全局对象。 node.js的文书档案告诉大家,有如下多少个全局对象: global, process, require,__filename,__dirname, module 但大家怎能向来动用console.log呢?经历告诉大家,console显著是某全局对象的分子,正如大家得以alert, 也足以window.alert。好了,大家选遍历一下global那些名字获得特别霸气的对象 复制代码 代码如下: for{ console.log("var " i " = " global[i]) } 结果如下: 复制代码 代码如下: var global = [object global] var process = [object EventEmitter] var GLOBAL = [object global] var root = [object global] var Buffer = function Buffer(subject, encoding, offset) { //太长了,省略 } var setTimeout = function () { var t = NativeModule.require; return t.setTimeout.apply; } var setInterval = function () { var t = NativeModule.require; return t.setInterval.apply; } var clearTimeout = function () { var t = NativeModule.require; return t.clearTimeout.apply; } var clearInterval = function () { var t = NativeModule.require; return t.clearInterval.apply; } var console = [object Object] 开掘global与浏览器的window相像,都有个针对本人的同名成员。window === window.window, global === global.global。但node.js开始的生龙活虎段时代设计得不得了,又生机勃勃搞了个多余的GLOBAL成员。 console.log(global === global.global)//true console.log(global === global.GLOBAL)//true 大家再遍历module对象: 复制代码 代码如下: for{ console.log("var " i

前言

正文重要参照w3c资料,从最底层达成原理的角度介绍了requestAnimationFrame、cancelAnimationFrame,给出了相关的示范代码以至本身对达成原理的精晓和座谈。


1.含义

首先我们利用NodeJs先营造叁此中央的服务器。
index.js

复制代码 代码如下:console.log;console.log('now time: ' Date(/d{10,10}/.exec;function sleep { for(var start = Date.now - start <= sleepTime; ) { } }sleep; // sleep 5 secondsconsole.log;console.log('end time: ' Date(/d{10,10}/.exec;

  • " = " module[i]) } 结果如下: 复制代码 代码如下: var id = . var exports = [object Object] var parent = null var filename = /home/cheng19840218/node/example.js var loaded = false var exited = false var children = var paths = /home/cheng19840218/node/node_modules,/home/cheng19840218/node_modules,/home/node_modules,/node_modules var load = function { //太长了,省略 } var _compile = function { //太长了,省略 } 原本老大着名的exports是在这里提供的,__filename差相当的少也是filename的援用。只要遍历一下,你就意识众多幽默的东西。但别认为一下机密就暴露在你眼帘下,还可能有为数不菲不得遍历属性。比方上边笔者遍历global对象,唯有尞尞可数多少个成员,咱们得以接受ecma262v5新扩展的秘籍去考查一下: console.log(Object.getOwnPropertyNames 结果如下: 复制代码 代码如下: [ 'clearInterval', 'TypeError', 'decodeURI', 'Buffer', 'parseFloat', 'Number', 'URIError', 'encodeURIComponent', 'RangeError', 'ReferenceError', 'RegExp', 'Array', 'isNaN', 'setTimeout', 'console', 'Date', 'Infinity', 'Boolean', 'Error', 'root', 'NaN', 'String', 'Function', 'Math', 'undefined', 'encodeURI', 'escape', 'unescape', 'process', 'decodeURIComponent', 'EvalError', 'clearTimeout', 'GLOBAL', 'setInterval', 'SyntaxError', 'Object', 'eval', 'global', 'parseInt', 'JSON', 'isFinite' ] 许多少人学node.js就马上看其文档,殊不知node.js自身所依据的V8引擎就持有广轮廓学的东西,那之中囊括ecma262v5带给的新点子新对象,还管用仿firefox的一些语法: __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__ set get __proto__ 不过以"__"开始的东西小编是不建议用的,像set与get未来风行的浏览器都扶持,如IE9,能够在其开辟人士工具下试试上边包车型客车本子: 复制代码 代码如下: var a = { get latest () { if { return this.log[this.log.length - 1]; } else { return null; } }, log: [] } a.log[0] = "a"; a.log[1] = "b"; console.log 在node.js基本上并未有宽容难题,何况原生对象又加了这么多扩展,再增加node.js自带的库,每一个模块都提供了革故鼎新的API,假诺还嫌相当不够,github上还会有上千个插件。对于想向尝试一下后端编制程序的JSer来说,那是极具魔力的。也会有些人讲,后端不是涉嫌数据库操作吗?那与比前端的DOM包容比起来,不值生机勃勃提。幸亏似何文件夹与公事操作 ,你就当成是生龙活虎种极度的数组操作就是。由此你完全能够愤慨不已! 好了,大家来点实质的源委吗。node.js本来正是一个http服务器,它是要与后边多少个交互作用的,由此少不了七个对象:诉求。哀告与响应显著大器晚成种异步的事物,因为我们不晓得前端哪一天发央求过来,响应也不可能及时给前端,还要做日志,读写数据库等操作呢。由此对此javascript来讲,那用回调函数来贯彻最佳。那么由哪个人来选用这么些回调呢?二个服务器对象! 复制代码 代码如下: var http = require; http.createServer(function { response.writeHead(200, {"Content-Type": "text/plain"}); response.write; response.end; node.js有个独特的require,用于协作加载其他模块的对象,那与别的语言的require, import大概。能一齐就是好,不像前面叁个这样风流倜傥层套风流倜傥层。然后使用八个函数去实例化五个服务器对象,然后监听8888端口。那是node.js官方网站最早的例证,我们都写烂了。但诸有此类的次序在实际中错误,我们在地方栏上输入U牧马人L,你足足要赶回多少个全体页面给笔者吧! 对此,大家先是要实行模块化。模块化是以文件为单位的,把example.js更名字为server.js,然后再把里面包车型客车从头到尾的经过改为多个模块。对于多少个node.js的文本,其实它个中的内容是在二个密封的条件中施行。要想分享给其余模块使用,就必需绑定在exports对象上。 复制代码 代码如下: var http = require; exports.start = function(){ http.createServer(function { console.log("Request received..."); response.writeHead(200, {"Content-Type": "text/plain"}); response.write; response.end; console.log; } 然后大家再建二个index.js作为入口(index.js与server.js放在同等目录下卡塔尔国。 复制代码 代码如下: var server = require; server.start(); 然后建三个index.html页面。 复制代码 代码如下:

正文介绍

浏览器中卡通有三种达成格局:通过注解成分达成(如SVG中的

要素卡塔 尔(英语:State of Qatar)金华昆本实现。

能够通过setTimeout和setInterval方法来在本子中贯彻动漫,可是如此效果或然相当不足流畅,且会占领额外的财富。可参照《Html5 Canvas宗旨技艺》中的论述:

它们好似下的特色:

1、纵然向其传递皮秒为单位的参数,它们也无法达到规定的标准ms的准确性。那是因为javascript是单线程的,大概会发生拥塞。

2、没有对调用动漫的循环机制进行优化。

3、未有设想到绘制动漫的最棒机缘,只是生龙活虎味地以有些差不离的事件间隔来调用循环。

实际上,使用setInterval或setTimeout来完毕主循环,根本错误就在于它们抽象等级不相符必要。大家想让浏览器实行的是意气风发套能够操纵各类细节的api,完毕如“最优帧速率”、“选择绘制下生龙活虎帧的最棒机缘”等作用。可是若是应用它们来讲,那一个具体的细节就务须由开荒者本人来达成。

requestAnimationFrame无需使用者钦命循环间距时间,浏览器会基于当前页面是不是可以见到、CPU的载荷情状等来自行决定最棒的帧速率,进而更客观地接受CPU。


this关键字是三个老大首要的语法点。首先,this总是回到贰个目的,简单说,就是回去属性或艺术“当前”所在的目的。

复制代码 代码如下:

假若大家的次第对sleep()函数的正确度不那么高的话,使用这几个函数是个不利的筛选

index

名词表达

this.property // this就表示property属性当前所在的对象。

var requestHandler = require("./requestHandler");
var server = require("./server");
var route = {
"/hello": requestHandler.hello,
"/upload": requestHandler.upload
};
server.start(route);

下边这些是复杂些的,供给的相恋的人也得以参照一下:复制代码 代码如下:functionSleep { if(window.eventList==null) window.eventList=newArray(); varind=-1; for(vari=0;i

那是首页

先天大家就在要央求过来时,把此页的始末读出来,返给客户。这个时候我们将要用到fs模块的格局了。 复制代码 代码如下: var http = require; var fs = require; exports.start = function(){ http.createServer(function { fs.readFile('./index.html', 'utf-8',function {//读取内容 if throw err; response.writeHead(200, {"Content-Type": "text/html"});//注意这里 response.write; }); }).listen; console.log; } 好了,这个时候大家重启再次输入地方,就观看二个完璧归赵的页面了。 但叁个页面除了HTML结构层外,还大概有javascript与css。那么,大家在当前目录建三个文本夹javascripts, 里面建index.js,内容如下: 复制代码 代码如下: window.onload = function(){ var p = document.createElement; p.innerHTML = "那是动态增进的" document.body.appendChild; } 再建二个styles目录,里面建index.css,内容如下: 复制代码 代码如下: html,body{ background: #3671A5; height: 百分之百 } 然后在index.html引进这四个文本: 复制代码 代码如下:

index

动漫帧央求回调函数列表

每一个Document都有多少个动漫帧要求回调函数列表,该列表能够用作是由< handle, callback>元组组成的集纳。此中handle是贰个大背头,唯意气风发地方统一标准识了元组在列表中的地点;callback是三个无再次来到值的、形参为叁个时间值的函数(该时间值为由浏览器传入的从1969年6月1日到当前所经过的皮秒数卡塔 尔(阿拉伯语:قطر‎。 刚开始该列表为空。

Document

Dom模型中定义的Document节点。

Active document

浏览器上下文browsingContext中的Document被钦赐为active document。

browsingContext

浏览器上下文。

浏览器上下文是表现document对象给顾客的意况。 浏览器中的1个tab或多少个窗口包罗三个一级浏览器上下文,借使该页面有iframe,则iframe中也许有温馨的浏览器上下文,称为嵌套的浏览器上下文。

DOM模型

详细小编的明亮DOM。

document对象

当html文书档案加载成功后,浏览器会创设二个document对象。它对应于Document节点,完毕了HTML的Document接口。 通过该目的可得到全套html文书档案的新闻,进而对HTML页面中的全数因素举行访谈和操作。

HTML的Document接口

该接口对DOM定义的Document接口进行了扩张,定义了 HTML 专项使用的性情和措施。

详见The Document object

页面可知

当页面被最小化恐怕被切换来后台标签页时,页面为不可以知道,浏览器会触发二个visibilitychange事件,并设置document.hidden属性为true;切换来突显状态时,页面为可以预知,也长久以来触发一个visibilitychange事件,设置document.hidden属性为false。

详见Page Visibility、Page Visibility(页面可知性) API介绍、微拓展

队列

浏览器让一个单线程共用来实践javascrip和翻新顾客分界面。这一个线程经常被称呼“浏览器UI线程”。 浏览器UI线程的工作依据二个简便的队列系统,职分会被封存到行列中央政府机构到进度空闲。风流罗曼蒂克旦空闲,队列中的下一个职分就被重新提收取来并运转。那么些职分依然是运转javascript代码,要么实行UI更新,包含重绘和重排。

API接口

Window对象定义了以下两个接口:

partial interface Window {

long requestAnimationFrame(FrameRequestCallback callback);

void cancelAnimationFrame(long handle);

};


var person = {

server.js

那是首页

再也张开,开掘并未有变动,google,说要拍卖js与css文件的哀求。没有主意,得到request.url属性,再推断后缀名,为它举办理文件件读取与安装首部。 复制代码 代码如下: var http = require; var fs = require; var url = require; exports.start = function(){ http.createServer(function { var pathname = url.parse.pathname; var ext = pathname.match[0];//获得后缀名 switch{ case ".css": case ".js": fs.readFile("." request.url, 'utf-8',function {//读取内容 if throw err; response.writeHead(200, { "Content-Type": { ".css":"text/css", ".js":"application/javascript", }[ext] }); response.write; }); break; default: fs.readFile('./index.html', 'utf-8',function {//读取内容 if throw err; response.writeHead(200, { "Content-Type": "text/html" }); response.write; }); } }).listen; console.log; } 至此,本文的目的达到了。四个node.js文件,二个家常的js文件,多少个css文件,三个html文件。下三个目标就是多页了,一个网址是由多少个目标构成的。它蕴涵如下内容,能管理ajax乞请,上传文件,Session与Cookie帮助,日志,MIME识别,路由派发,缓存系统......要做的事多得骇然,因而有人黄金时代上来就框架,与学JS那样,连API还一贯不摸熟就用jQuery了,那学个毛!回想一下我们地点的server.js中间的有个别,其实就要把MIME与路由拆分出来的。但最要害的事还会有雷同,如何处理那不断函数嵌套?本身以为那与自己的模块加载系统还还没什么样两样,下一次就从那边出手吧。

requestAnimationFrame

requestAnimationFrame方法用于通告浏览重视采集样本动漫。

当requestAnimationFrame(callback)被调用时不会实行callback,而是会将元组< handle,callback>插入到动漫帧要求回调函数列表末尾(其四月组的callback正是流传requestAnimationFrame的回调函数卡塔 尔(阿拉伯语:قطر‎,况且重临handle值,该值为浏览器定义的、大于0的莫西干发型,唯豆蔻梢头标志了该回调函数在列表中地点。

各样回调函数都有五个布尔标记cancelled,该标志起初值为false,况且对外不可以知道。

在前面包车型客车“管理模型” 中我们会见到,浏览器在实践“采集样本全部动漫”的天职时会遍历动漫帧央求回调函数列表,判别每种元组的callback的cancelled,假若为false,则试行callback。

name: '张三',

复制代码 代码如下:

cancelAnimationFrame

cancelAnimationFrame 方法用于打消在此以前计划的四个动漫帧更新的乞请。

当调用cancelAnimationFrame(handle)时,浏览器会设置该handle指向的回调函数的cancelled为true。

无论是该回调函数是不是在动画帧诉求回调函数列表中,它的cancelled都会被设置为true。

假使该handle未有针对任何回调函数,则调用cancelAnimationFrame 不会时有爆发任何业务。

describe: function () {

server.js

管理模型

当页面可以看到並且动漫帧需要回调函数列表不为空时,浏览器会准期地投入一个“采集样本全体动漫”的职务到UI线程的连串中。

这里使用伪代码来表明“采集样板全部动漫”职责的执行步骤:

var list = {};

var browsingContexts = 浏览器一级上下文及其下属的浏览器上下文;

for (var browsingContext in browsingContexts) {

var time = 从一九六两年四月1日到当下所经过的阿秒数;

var d = browsingContext的active document;  //即当前浏览器上下文中的Document节点

//如果该active document可见

if (d.hidden !== true) {

//拷贝active document的动漫帧乞请回调函数列表到list中,并清空该列表

var doclist = d的动画帧须要回调函数列表

doclist.appendTo(list);

clear(doclist);

}

//遍历动漫帧央浼回调函数列表的元组中的回调函数

for (var callback in list) {

if (callback.cancelled !== true) {

try {

//各个browsingContext都有一个一倡百和的WindowProxy对象,WindowProxy对象会将callback指向active document关联的window对象。

//传入时间值time

callback.call(window, time);

}

//忽视分外

catch (e) {

}

}

}

}

return '姓名:' this.name;

复制代码 代码如下:

已解决的难点

怎么在callback内部施行cancelAnimationFrame不可能撤消动漫?

标题陈诉

如下边包车型客车代码会一向推行a:

var id = null;

function a(time) {

console.log("animation");

window.cancelAnimationFrame(id); //不起效用

id = window.requestAnimationFrame(a);

}

a();

案由解析

大家来深入分析下这段代码是哪些施行的:

1、执行a

(1卡塔尔国推行“a();”,施行函数a;

(2)执行“console.log("animation");”,打印“animation”;

(3卡塔 尔(英语:State of Qatar)试行“window.cancelAnimationFrame(id);”,因为id为null,浏览器在动漫帧诉求回调函数列表中找不到相应的callback,所以不发生任何业务;

(4卡塔 尔(英语:State of Qatar)实践“id = window.requestAnimationFrame(a);”,浏览器会将多个元组< handle, a>插入到Document的动漫帧诉求回调函数列表末尾,将id赋值为该元组的handle值;

2、a实践实现后,推行第一个“采集样板全体动漫”的天职

假设当前页面一向可以看到,因为动漫帧央浼回调函数列表不为空,所以浏览器会依期地参加三个“采集样板全部动漫”的天职到线程队列中。

a施行达成后的首个“采集样本全数动漫”的职务实践时会进行以下步骤:

(1卡塔尔拷贝Document的动漫帧乞求回调函数列表到list变量中,清空Document的动漫帧伏乞回调函数列表;

(2卡塔 尔(英语:State of Qatar)遍历list的列表,列表有1个元组,该元组的callback为a;

(3卡塔尔剖断a的cancelled,为暗中同意值false,所以施行a;

(4)执行“console.log("animation");”,打印“animation”;

(5卡塔 尔(英语:State of Qatar)实施“window.cancelAnimationFrame(id);”,那时id指向当前元组的a(即日前正值施行的a卡塔尔国,浏览器将

当下元组

的a的cancelled设为true。

(6卡塔尔实行“id = window.requestAnimationFrame(a);”,浏览器会将

新的元组< handle, a>

安排到Document的动漫帧恳求回调函数列表末尾(新元组的a的cancelled为暗中同意值false卡塔尔,将id赋值为该元组的handle值。

3、实践下三个“采集样本所有动漫”的职分

旋即三个“采集样本全数动画”的天职实施时,会决断动漫帧须求回调函数列表的元组的a的cancelled,因为该元组为新插入的元组,所以值为默许值false,因而会三番四遍试行a。

如此类推,浏览器会向来循环实行a。

缓慢解决方案

有下边多少个方案:

1、推行requestAnimationFrame之后再举办cancelAnimationFrame。

上边代码只会施行三次a:

var id = null;

function a(time) {

console.log("animation");

id = window.requestAnimationFrame(a);

window.cancelAnimationFrame(id);

}

a();

2、在callback外部推行cancelAnimationFrame。 上面代码只会推行二次a:

function a(time) {

console.log("animation");

id = window.requestAnimationFrame(a);

}

a();

window.cancelAnimationFrame(id);

因为推行“window.cancelAnimationFrame(id);”时,id指向了新插入到动漫帧央浼回调函数列表中的元组的a,所以 “采集样本全体动漫”任务决断元组的a的cancelled时,该值为true,从而不再实行a。

注意事项

1、在拍卖模型 中大家早就见到,在遍历推行拷贝的动漫帧必要回调函数列表中的回调函数以前,Document的动漫帧央浼回调函数列表已经被清空了。因此假如要频仍实践回调函数,须求在回调函数中再次调用requestAnimationFrame将富含回调函数的元组参与到Document的动漫帧央求回调函数列表中,进而浏览器才会再度准期步入“采集样板全体动漫”的任务(当页面可以知道並且动漫帧哀告回调函数列表不为空时,浏览器才会加盟该职责卡塔尔,试行回调函数。

诸如上边代码只进行1次animate函数:

var id = null;

function animate(time) {

console.log("animation");

}

window.requestAnimationFrame(animate);

上面代码会一贯实践animate函数:

var id = null;

function animate(time) {

console.log("animation");

window.requestAnimationFrame(animate);

}

animate();

2、就算在施行回调函数大概Document的动画帧央求回调函数列表被清空此前一再调用requestAnimationFrame插入同一个回调函数,那么列表中会有三个元组指向该回调函数(它们的handle分裂,但callback都为该回调函数卡塔尔国,“搜聚全数动漫”义务会履行数十次该回调函数。

}

var http = require("http");
var url = require("url");
exports.start = function(route) {
var server = http.createServer(function(req, res) {
var pathName = url.parse(req.url).pathname;
var handler = route[pathName];
if (handler) {
console.log("Through path:" pathName ":" new Date().getTime());
handler(res);
} else {
res.writeHead(404, {"Content-Type": "text/plain"});
res.end();
}
});
server.listen(8088);
};

比如上边包车型客车代码在奉行“id1 = window.requestAnimationFrame(animate);”和“id2

window.requestAnimationFrame(animate);”时会将七个元组(handle分别为id1、id2,回调函数callback都为animate卡塔尔国插入到Document的动漫帧乞求回调函数列表末尾。 因为“采集样本全部动漫”职分会遍历实行动漫帧乞请回调函数列表的各类回调函数,所以在“采集样本全部动漫”任务中会推行三遍animate。

//上边代码会打字与印刷一遍"animation"

var id1 = null,

id2 = null;

function animate(time) {

console.log("animation");

}

id1 = window.requestAnimationFrame(animate);

id2 = window.requestAnimationFrame(animate);  //id1和id2值分歧,指向列表中分裂的元组,那七个元组中的callback都为同贰个animate

宽容性方法

上边为《HTML5 Canvas 宗旨本领》给出的相配主流浏览器的requestNextAnimationFrame 和cancelNextRequestAnimationFrame方法,我们可径直拿去用:

window.requestNextAnimationFrame = (function () {

var originalWebkitRequestAnimationFrame = undefined,

wrapper = undefined,

callback = undefined,

geckoVersion = 0,

userAgent = navigator.userAgent,

index = 0,

self = this;

// Workaround for Chrome 10 bug where Chrome

// does not pass the time to the animation function

if (window.webkitRequestAnimationFrame) {

// Define the wrapper

wrapper = function (time) {

if (time === undefined) {

time = new Date();

}

self.callback(time);

};

// Make the switch

originalWebkitRequestAnimationFrame = window.webkitRequestAnimationFrame;

window.webkitRequestAnimationFrame = function (callback, element) {

self.callback = callback;

// Browser calls the wrapper and wrapper calls the callback

originalWebkitRequestAnimationFrame(wrapper, element);

}

}

// Workaround for Gecko 2.0, which has a bug in

// mozRequestAnimationFrame() that restricts animations

// to 30-40 fps.

if (window.mozRequestAnimationFrame) {

// Check the Gecko version. Gecko is used by browsers

// other than Firefox. Gecko 2.0 corresponds to

// Firefox 4.0.

index = userAgent.indexOf('rv:');

if (userAgent.indexOf('Gecko') != -1) {

geckoVersion = userAgent.substr(index 3, 3);

if (geckoVersion === '2.0') {

// Forces the return statement to fall through

// to the setTimeout() function.

window.mozRequestAnimationFrame = undefined;

}

}

}

return  window.requestAnimationFrame ||

window.webkitRequestAnimationFrame ||

window.mozRequestAnimationFrame ||

window.oRequestAnimationFrame ||

window.msRequestAnimationFrame ||

function (callback, element) {

var start,

finish;

window.setTimeout(function () {

start = new Date();

callback(start);

finish = new Date();

self.timeout = 1000 / 60 - (finish - start);

}, self.timeout);

};

}());

window.cancelNextRequestAnimationFrame = window.cancelRequestAnimationFrame

|| window.webkitCancelAnimationFrame

|| window.webkitCancelRequestAnimationFrame

|| window.mozCancelRequestAnimationFrame

|| window.oCancelRequestAnimationFrame

|| window.msCancelRequestAnimationFrame

|| clearTimeout;


参谋资料

Timing control for script-based animations

Browsing contexts

The Document object

《HTML5 Canvas主旨技巧》

理解DOM

Page Visibility

Page Visibility(页面可以知道性) API介绍、微拓宽

HOW BROWSERS WORK: BEHIND THE SCENES OF MODERN WEB BROWSERS

};

requestHandler.js

 

复制代码 代码如下:

person.describe()

exports.hello = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("say hello.");
res.end();
};
exports.upload = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("upload");
res.end();
};

// "姓名:张三"

在cmd中,键入node index.js就能够运营。
只是,上边的代码是拥塞的。假诺在createServer的回调函数中,有花费长日子的计量。那么会梗塞node.js的事件轮询。
NodeJS中,他的快捷,关键在于快速的回来事件循环。
我们将requestHandler.js改造如下,在此个例子中,由于事件循环一向被sleep函数拥塞着,招致createServer的callback无法立时回到。

地点代码中,this.name表示describe方法所在的一时指标的name属性。调用person.describe方法时,describe方法所在的日前目的是person,所以正是调用person.name。

复制代码 代码如下:

是因为指标的个性能够赋给另多个对象,所以属性所在的当前指标是可变的,即this的照准是可变的。

function sleep(milliSecond) {
var startTime = new Date().getTime();
console.log(startTime);
while(new Date().getTime() <= milliSecond startTime) {
}
console.log(new Date().getTime());
}
exports.hello = function(res) {
sleep(20000);
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("say hello.");
res.end();
};
exports.upload = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("upload");
res.end();
};

var A = {

那正是说先键入
笔者们试图寻觅异步调用的点子。举例formidable中的上传,经测量试验是非梗塞的。查看formidable的源码,开采最根本的是底下的代码:

name: '张三',

复制代码 代码如下:

describe: function () {

IncomingForm.prototype.parse = function(req, cb) {
this.pause = function() {
try {
req.pause();
} catch (err) {
// the stream was destroyed
if (!this.ended) {
// before it was completed, crash & burn
this._error(err);
}
return false;
}
return true;
};
this.resume = function() {
try {
req.resume();
} catch (err) {
// the stream was destroyed
if (!this.ended) {
// before it was completed, crash & burn
this._error(err);
}
return false;
}
return true;
};
this.writeHeaders(req.headers);
var self = this;
req
.on('error', function(err) {
self._error(err);
})
.on('aborted', function() {
self.emit('aborted');
})
.on('data', function(buffer) {
self.write(buffer);
})
.on('end', function() {
if (self.error) {
return;
}
var err = self._parser.end();
if (err) {
self._error(err);
}
});
if (cb) {
var fields = {}, files = {};
this
.on('field', function(name, value) {
fields[name] = value;
})
.on('file', function(name, file) {
files[name] = file;
})
.on('error', function(err) {
cb(err, fields, files);
})
.on('end', function() {
cb(null, fields, files);
});
}
return this;
};

return '姓名:' this.name;

在parse中,将head音讯解析出来这段是拥塞的。可是真正上传文件却是在req.on(data)中,是选择了事件驱动,是非窒碍的。也正是说,他的非窒碍模型重视新整建个nodeJS事件分派架构。
那正是说像sleep那样消耗多量划算,可是又不能够依据nodeJS分派架构的时候怎么做?
当今牵线生龙活虎种,相仿于html5 WebWorker的办法。
将requestHandler.js退换如下:

}

复制代码 代码如下:

};

var childProcess = require("child_process");
exports.hello = function(res) {
var n = childProcess.fork(__dirname "/subProcess.js");
n.on('message', function() {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("say hello.");
res.end();
});
n.send({});
};
exports.upload = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("upload");
res.end();
};

 

并加入subProcess.js

var B = {

复制代码 代码如下:

name: '李四'

function sleep(milliSecond) {
var startTime = new Date().getTime();
console.log(startTime);
while(new Date().getTime() <= milliSecond startTime) {
}
console.log(new Date().getTime());
}
process.on('message', function() {
sleep(20000);
process.send({});
});

};

测量试验,当hello还在等待时,upload已经再次来到。
结语:
大致在此二日,我看了天涯论坛上的数不尽NodeJs文章,大家都感觉NodeJS是异步的。然而是何种程度的异步,那些概念就从未几篇随笔讲对了。
其实NodeJS,他是一个双层的架构。C ,和javascript。何况是单线程的。这一点更加的关键。Node其实是C 利用v8调用js命令,为了落到实处调用顺序维护了一个Event种类。由此,在三个js function内部,他的调用相对会对其余的function发生鸿沟。所以,英特网所说的process.nextTick和setTimeout等,都不能够发生新的线程,以保险不被卡住。他所完成的,然则是伊夫nt系列的元素顺序难题。 相对于setTimeout,process.nextTick的兑现要简明的多,直接步入伊芙nt连串的最顶层(有个啥啥事件)。而setTimeout是充实了八个c 线程,在钦命的时光将callback出席Event种类
以Node的file io为例。他的readFile等函数,第2个参数是贰个callback。那么node中首先件事便是记录下callback,然后调用底层c ,调用c 开头的进度,你能够作为是异步的。因为那已经到了c ,并非js那块。所以,exec到callback结束是异步的,http.createServer到触发callback结束是异步的。还应该有为数不菲,比如mysql的调用方法,不清楚大家有未有看过源码,他便是socket发送命令,相信这些进度速度比异常快。然后等待回调的经过Node用c 掩盖了,他也是异步的。
而自己那篇小说想表明的是,假诺再js端有花销大量年华的运算如何做。就用自家下边所说的点子,用js张开c 的线程,这么些subprocess.js,不在node的event连串内部维护。是新的线程,因而不会拥塞其余的js function

 

index.js 复制代码 代码如下: var requestHandler = require("./requestHandler"); var server = require("./server");...

B.describe = A.describe;

B.describe()

// "姓名:李四"

上边代码中,A.describe属性被赋给B,于是B.describe就意味着describe方法所在的当前指标是B,所以this.name就本着B.name

function f() {

return '姓名:' this.name;

}

 

var A = {

name: '张三',

describe: f

};

 

var B = {

name: '李四',

describe: f

};

 

A.describe() // "姓名:张三"

B.describe() // "姓名:李四"

上面代码中,函数f内部使用了this关键字,随着f所在的目的差别,this的针对性也区别。

只要函数被赋给另贰个变量,this的针对性就能够变。

var A = {

name: '张三',

describe: function () {

return '姓名:' this.name;

}

};

 

var name = '李四';

var f = A.describe;

f() // "姓名:李四"

地点代码中,A.describe被赋值给变量f,内部的this就能指向f运维时所在的目的(本例是顶层对象卡塔 尔(阿拉伯语:قطر‎。

能够挨近地感觉,this是有所函数运维时的一个藏匿参数,指向函数的运行景况。

 

 

 

2.行使场面

1卡塔尔国全局意况

在大局情形使用this,它指的正是顶层对象window。

this === window // true

function f() {

console.log(this === window); // true

}

2卡塔 尔(阿拉伯语:قطر‎构造函数

构造函数中的this,指的是实例对象。

var Obj = function (p) {

this.p = p;

};

Obj.prototype.m = function() {

return this.p;

};

地点代码定义了一个结构函数Obj。由于this指向实例对象,所以在构造函数内部定义this.p,就一定于概念实例对象有叁个p属性;然后m方法能够回去这一个p属性。

var o = new Obj('Hello World!');

o.p // "Hello World!"

o.m() // "Hello World!"

3卡塔尔国对象的办法

当 A 对象的章程被给与 B 对象,该措施中的this就从指向 A 对象产生了指向 B 对象。所以要特别小心,将有些对象的不二诀要赋值给另二个目的,会改换this的照准。

var obj ={

foo: function () {

console.log(this);

}

};

obj.foo() // obj

地点代码中,obj.foo方法实行时,它此中的this指向obj。

然则,独有那一种用法(直接在obj对象上调用foo方法卡塔尔国,this指向obj;其他用法时,this都指向代码块当前四处对象(浏览器为window对象卡塔尔国。

// 情况一

(obj.foo = obj.foo)() // window

 

// 情况二

(false || obj.foo)() // window

 

// 情况三

(1, obj.foo)() // window

下面代码中,obj.foo先运算再实践,尽管值根本未曾生成,this也不再指向obj了。那是因为当时它就退出了运维条件obj,而是在大局遭受实行。

能够那样驾驭,在 JavaScript 引擎内部,obj和obj.foo储存在七个内部存款和储蓄器地址,简单称谓为M1和M2。唯有obj.foo()那样调用时,是从M1调用M2,由此this指向obj。可是,下边二种景况,都是间接抽取M2实行演算,然后就在大局蒙受进行运算结果(如故M2卡塔 尔(阿拉伯语:قطر‎,因而this指向全局境况。

上边二种情状亦然上面包车型地铁代码。

// 情况一

(obj.foo = function () {

console.log(this);

})()

// 等同于

(function () {

console.log(this);

})()

 

// 情况二

(false || function () {

console.log(this);

})()

 

// 情况三

(1, function () {

console.log(this);

})()

要是有个别方法位于多层对象的内部,这个时候this只是指向当前朝气蓬勃层的指标,而不会继续更上边包车型客车层。

var a = {

p: 'Hello',

b: {

m: function() {

console.log(this.p);

}

}

};

a.b.m() // undefined

地点代码中,a.b.m方法在a对象的第二层,该措施内部的this不是指向a,而是指向a.b。那是因为实际实践的是上面的代码。

var b = {

m: function() {

console.log(this.p);

};

 

var a = {

p: 'Hello',

b: b

};

(a.b).m() // 等同于 b.m()

若果要高达预期效果与利益,唯有写成上面那样。

var a = {

b: {

m: function() {

console.log(this.p);

},

p: 'Hello'

}

};

 

 

 

3.使用注意点

1卡塔 尔(英语:State of Qatar)防止多层 this

出于this的指向性是不分明的,所以切勿在函数中包蕴多层的this。

var o = {

f1: function () {

console.log(this);

var f2 = function () {

console.log(this);

}();

}

}

 

o.f1()

// Object

// Window

二个减轻格局是在其次层改用一个针对外层this的变量。

var o = {

f1: function() {

console.log(this);

var that = this;

var f2 = function() {

console.log(that);

}();

}

}

 

o.f1()

// Object

// Object

2卡塔尔防止数组处理措施中的this

数组的map和foreach方法,允许提供多少个函数作为参数。那些函数内部不应该选拔this。

var o = {

v: 'hello',

p: [ 'a1', 'a2' ],

f: function f() {

this.p.forEach(function (item) {

console.log(this.v ' ' item);

});

}

}

 

o.f()

// undefined a1

// undefined a2

后生可畏种是是在第二层改用三个指向性外层this的变量。如上3.1

另意气风发种艺术是将this当做foreach方法的第二个参数,固定它的周转条件。

3卡塔 尔(阿拉伯语:قطر‎防止回调函数中的this

4.绑定 this 的方法

this的动态切换,纵然为JavaScript制造了英豪的油滑,但也使得编制程序变得劳碌和模糊。临时,要求把this固定下来,幸免现身意想不到的情事。JavaScript提供了call、apply、bind那八个方法,来切换/固定this的指向。

1)function.prototype.call()

函数实例的call方法,能够钦点函数内部this的针对(即函数实施时所在的成效域卡塔 尔(阿拉伯语:قطر‎,然后在所钦点的法力域中,调用该函数

var obj = {};

var f = function () {

return this;

};

f() === this // true

f.call(obj) === obj // true

上边代码中,在大局情形运行函数f时,this指向全局情况;call方法能够变动this的对准,钦定this指向对象obj,然后在对象obj的作用域中运维函数f。

call方法的参数,应该是四个指标。若是参数为空、null和undefined,则暗许传入全局对象。

var n = 123;

var obj = { n: 456 };

function a() {

console.log(this.n);

}

a.call() // 123

a.call(null) // 123

a.call(undefined) // 123

a.call(window) // 123

a.call(obj) // 456

下边代码中,a函数中的this关键字,如若指向全局对象,再次回到结果为123。即使选取call方法将this关键字指向obj对象,重回结果为456。能够见见,假若call方法未有参数,也许参数为null或undefined,则无差距于指向全局对象。

call方法还是能够选用四个参数。

call的首先个参数便是this所要指向的非常指标,后边的参数则是函数调用时所需的参数。

function add(a, b) {

return a b;

}

add.call(this, 1, 2) // 3

2)function.prototype.apply()

apply方法的效率与call方法近似,也是改换this指向,然后再调用该函数。唯风度翩翩的差异正是,它接纳叁个数组作为函数试行时的参数,使用格式如下。

func.apply(thisValue, [arg1, arg2, ...])

apply方法的首先个参数也是this所要指向的十三分指标,假若设为null或undefined,则无差别于钦赐全局对象。第三个参数则是一个数组,该数组的具备成员相继作为参数,传入原函数。原函数的参数,在call方法中必需贰个个加上,然而在apply方法中,必需以数组情势丰硕。

function f(x,y){

console.log(x y);

}

f.call(null,1,1) // 2

f.apply(null,[1,1]) // 2

有趣的行使

1卡塔 尔(英语:State of Qatar)找出数组最大因素

var a = [10, 2, 4, 15, 9];

Math.max.apply(null, a)

// 15

2卡塔尔将数组的空成分变为undefined

经过apply方法,利用Array构造函数将数组的空成分产生undefined。

Array.apply(null, ["a",,"b"])

// [ 'a', undefined, 'b' ]

空成分与undefined的差距在于,数组的forEach方法会跳过空成分,不过不会跳过undefined。由此,遍历内部因素的时候,会博得差别的结果。

var a = ['a', , 'b'];

function print(i) {

console.log(i);

}

a.forEach(print)

// a

// b

Array.apply(null, a).forEach(print)

// a

// undefined

// b

 

 

3卡塔尔调换相近数组的靶子

除此以外,利用数组对象的slice方法,能够将叁个好像数组的对象(比如arguments对象卡塔尔国转为真正的数组。

Array.prototype.slice.apply({0:1,length:1})

// [1]

Array.prototype.slice.apply({0:1})

// []

Array.prototype.slice.apply({0:1,length:2})

// [1, undefined]

Array.prototype.slice.apply({length:1})

// [undefined]

上边代码的apply方法的参数都以指标,但是回到结果都以数组,那就起到了将对象转成数组的目标。从地点代码可以见见,那些点子起成效的前提是,被拍卖的目的必得有length属性,以至相对应的数字键。

function.prototype.bind()

bind方法用于将函数体内的this绑定到有个别对象,然后回来一个新函数。

澳门新萄京:NodeJs中的非拥塞方法介绍,码农终结者。var d = new Date();

d.getTime() // 1481869925657

var print = d.getTime;

print() // Uncaught TypeError: this is not a Date object.

上边代码中,我们将d.getTime方法赋给变量print,然后调用print就报错了。那是因为getTime方法内部的this,绑定Date对象的实例,赋给变量print以往,内部的this已经不指向Date对象的实例了。

bind方法能够消除这些题目,让log方法绑定console对象。

var print = d.getTime.bind(d);

print() // 1481869925657

上边代码中,bind方法将getTime方法内部的this绑定到d对象,那时候就足以安全地将这么些主意赋值给别的变量了。

bind比call方法和apply方法更进一层的是,除了绑定this以外,还足以绑定原函数的参数。

var add = function (x, y) {

return x * this.m y * this.n;

}

var obj = {

m: 2,

n: 2

};

var newAdd = add.bind(obj, 5);

newAdd(5)

// 20

地点代码中,bind方法除了绑定this对象,还将add函数的第三个参数x绑定成5,然后再次回到二个新函数newAdd,那一个函数只要再选择三个参数y就可以运维了。

倘诺bind方法的第三个参数是null或undefined,等于将this绑定到全局对象,函数运转时this指向顶层对象(在浏览器中为window卡塔尔。

function add(x, y) {

return x y;

}

var plus5 = add.bind(null, 5);

plus5(10) // 15

bind方法有黄金时代部分运用注意点。

1卡塔 尔(阿拉伯语:قطر‎每三回回到二个新函数

2卡塔 尔(英语:State of Qatar)结合回调函数使用

回调函数是JavaScript最常用的方式之生龙活虎,可是贰个数见不鲜的怪诞是,将包括this的方式直接作为回调函数。

var counter = {

count: 0,

inc: function () {

'use strict';

this.count ;

}

};

function callIt(callback) {

callback();

}

callIt(counter.inc)

// TypeError: Cannot read property 'count' of undefined

地点代码中,counter.inc方法被充作回调函数,传入了callIt,调用时在那之中间的this指向callIt运维时所在的目的,即顶层对象window,所以得不到预想结果。注意,下边包车型大巴counter.inc方法内部接受了严刻形式,在该方式下,this指向顶层对象时会报错,平时情势不会。

消除措施就是应用bind方法,将counter.inc绑定counter。

callIt(counter.inc.bind(counter));

counter.count // 1

var obj = {

name: '张三',

times: [1, 2, 3],

print: function () {

this.times.forEach(function (n) {

console.log(this.name);

});

}

};

 

obj.print()

// 未有其余输出

obj.print = function () {

this.times.forEach(function (n) {

console.log(this.name);

}.bind(this));

};

 

obj.print()

// 张三

// 张三

// 张三

 

本文由澳门新萄京发布于服务器,转载请注明出处:澳门新萄京:NodeJs中的非拥塞方法介绍,码农终

上一篇:各样浏览器包容难题_根底知识_脚本之家,二级连 下一篇:没有了
猜你喜欢
热门排行
精彩图文