乐亭徐州华为手机售后在哪哪

很多人在用NodeJs的setTimeout(callback, delay[, arg][, ...])编写定时任务时,习惯上直接操作callback外部的对象object(闭包的特点)。这样做有一个隐患,就是当callback真正执行的时候,外部对象object可能已经被销毁了(比如执行了自定义的销毁方法),导致对object进行的处理结果出现了很大的偏差,程序甚至有可能出现异常而退出。
解决这个问题其实很简单,我们只需要在callback回调中重新通过某种方式获取该对象,检查一下该对象是否已被销毁,即可避免上面描述的问题。但是,当程序中需要很多这样的需求时,并且是一个团队在合作写代码,这样就很难避免上述情况的发生。为了规避定时任务的闭包问题,我写了一个延迟调用类,代码如下:
* script: delayCall.js
* description: 延迟调用,规避定时任务的闭包问题
* authors:
var util = require('util');
var PQueue = require('./pqueue').PQ
* 延迟调用类
* @param search_func 对象查找函数
var DelayCall = exports.DelayCall = function(search_func) {
//延迟调用序号
this._call_seq = 0;
//延迟调用映射
this._call_map = {};
//延迟调用队列
this._call_queue = new pare);
//对象查找方法
this._search_func = search_
//设置间隔定时器。FIXME:可以改为在框架的心跳机制中去执行run方法
//注:setTimeout不支持修改系统时间
this._interval_id = setInterval(() =& {
this.run();
//比较延迟调用
pare = function(call1, call2) {
var time_diff = call1.exec_time - call2.exec_
if (time_diff) {
return time_
return call1._call_id - call2._call_
//延迟调用序号自增
DelayCall.prototype._addSequence = function() {
return ++ this._call_
* 延迟调用
* @param id 对象查找方法_search_func根据id查找出调用者对象
* @param method_name 调用者对象上要延迟调用的方法名
* @param params 要延迟调用的方法参数
* @param delay 延迟时间,单位秒
DelayCall.prototype.call = function(id, method_name, params, delay) {
var call_id = this._addSequence();
var exec_time = Date.now() + delay * 1000;
var call_elem = {
_call_id: call_id,
method_name: method_name,
params: params,
delay: delay,
exec_time: exec_time,
_canceled: false,
this._call_queue.enQueue(call_elem);
this._call_map[call_id] = call_
return call_
//取消延迟调用
DelayCall.prototype.cancelCall = function(call_id) {
var call_elem = this._call_map[call_id];
if (call_elem) {
delete this._call_map[call_id];
call_elem._canceled =
//运转一次
DelayCall.prototype.run = function() {
var now = Date.now();
var pqueue = this._call_
var search_func = this._search_
var call_elem = pqueue.getHead();
while (call_elem) {
if (call_elem._canceled) {
pqueue.deQueue();
if (now & call_elem.exec_time) {
//从队列和映射中删除
pqueue.deQueue();
delete this._call_map[call_elem._call_id];
//执行对象的方法
var obj = search_func(call_elem.id);
if (obj && typeof obj[call_elem.method_name] == 'function') {
obj[call_elem.method_name](call_elem.params);
call_elem = pqueue.getHead();
&PQueue的实现请参考我的饿另一篇博文:
阅读(...) 评论()问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
var array = [1,2,3,4];
function check()
if(array.length & 0)
var url = array.pop();
load(url);
function load(url)
http.get(url, function(res){
我想在 每次load(url)的时候 延迟6秒 这时候我用setTimeout 没什么效果
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
发代码的时候最好format一下啊!亲
如用setTimeout实现你需要递归一下
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
定时函数可以这么写
var a = function(){
setTimeout(() =& {
不知道是不是你想要的意思
同步到新浪微博
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 Appnodejs http 请求延时的处理方法(防止程序崩溃)
时间: 22:37:24
&&&& 阅读:251
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&有时候因为接口没开,或者其他原因,导致http.request 请求延时,一直耗费资源不说,还会导致程序报错崩溃,延时处理其实也是一种错误处理。
直接上代码:
var APIGET = function (url, callback) {
debug("向API服务请求数据中...");
debug("url:"+url)
//下面是发送请求时的延时处理,一般用不到
var requestTimer = setTimeout(function () {
req.abort();
debug(‘......Request Timeout......‘);
var op = {
host:CONFIG.API_SERVICE_HOST,
port:CONFIG.API_SERVICE_PORT,
method:‘GET‘,
var req = HTTP.request(
op,function(res) {
clearTimeout(requestTimer);
//下面是请求接口数据,得不到回应时,我们关闭等待返回数据的状态,因为有5秒的定时器,
//5秒内如果收到了完整的数据,http模块会自动跳转到res.on(‘end‘, function(){})
//因为我们在res.on(‘end‘, function(){})的回调函数中clearTimeout(responseTimer),
//清除了这个定时器,所以就不用担心在接受到数据后定时器还反复执行。
var responseTimer = setTimeout(function () {
res.destroy();
debug(‘......Response Timeout......‘);
var recvData = "";
res.on(‘data‘, function(chunk) {
recvData +=
// debug(recvData);
res.on(‘end‘, function() {
clearTimeout(responseTimer);
if (callback) {
callback(null, JSON.parse(recvData));
debug("请求结束");
req.on(‘error‘, function (e) {
if (callback) {
callback(e, null);
req.end();
  标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!nodejs中实现sleep功能实例
投稿:junjie
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了nodejs中实现sleep功能实例,本文讲解了sleep功能的开发过程和使用效果及性能测试,需要的朋友可以参考下
nodejs最让人不爽的就是其单线程特性,很多事情没法做,对CPU密集型的场景,性能也不够强劲。很长一段时间,我想在javascript语言框架下寻求一些解决方案,解决无法操作线程、性能差的问题。曾经最让我印象深刻的方案是,不过fibers也好,其他方案也好,在线程操作上还是很别扭,太过依赖辅助线程,本末倒置;就fiber而言,javascript固有的低性能问题并不能解决;最别扭的是在javascript语言框架下,线程间的消息传递常常很受限制,经常无法真正地共享对象。
nodejs的addon方式无疑是极好的,具有极强的灵活性、完备的功能和原生代码的性能。简单说就是让nodejs直接调用c/c++模块,是一种javascript和native的混合开发模式。好东西呀,为什么不用呢?addon应该算是一个大话题,今天我也不想太深入说这个,我自己的实践也不是很多。那就实现一个sleep函数,就当是抛砖引玉吧。
为什么javascript实现不了真正的sleep?sleep方法是通过向操作系统内核注册一个信号,指定时间后发送唤醒信号,而线程本身则挂起。本质上当线程 sleep(1000) 代表告诉操作系统:1000ms内不要给我分配CPU时间。所以sleep能保证线程挂起时不再占用CPU资源。而javascript是单线程运行,本身取消了线程的概念,自然没有办法将主线程挂起中断。
也有人会尝试用javascript方法要实现sleep,例如这样:
function sleep(sleepTime) {
&&& for(var start = +new D +new Date - start &= sleepT ) { }
这是采用空循环阻塞住主进程的运行来实现sleep,明显跟真正的sleep相去甚远。
那么如果实现一个真正的sleep呢?
之前我的一些博客已经说过,这里从略:node.js+npm、python 2.7、visual studio/ x-code。
编译工具需要采用node-gyp,较新版本的nodejs自带此库,如果没有自带node-gyp,请执行:
npm install -g node-gyp
&gyp特性我没有精力去研究,如果你比较熟悉gcc等其他编译器,不排除gyp会有不兼容之处,而且编译选项和开关也是不尽相同。建议针对nodejs重新编写c++代码,如果确实有模块需要复用,可以考虑先用熟悉的gcc编译成动态链接库,再编写少量代码来使用动态链接库,再把这部分代码用gyp编译出来供nodejs使用。
进入项目文件夹,执行 npm init 初始化项目。为了让nodejs知道我们想制作addon,我们需要在package.json中添加:
"gyp-file": true
如果使用过gcc,那么你一定记得makefile。类似的,gyp也是通过一个文件来描述编译配置,这个文件为binding.gyp,它是一个我们非常熟悉的json文件。gyp不是我们探讨的重点,所以binding.gyp也不会深入探究,我们只关注最重要的一些配置项。以下是一份简单但完整的binding.gyp文件示例:
& "targets": [
&&&&& "target_name": "hello",
&&&&& "sources": [ "hello.cc" ],
&&&&& "include_dirs": [
&&&&&&& "&!(node -e \"require('nan')\")"
就看看这里面涉及的三个配置项:
1.target_name:表示输出出来的模块名。
2.sources:表示需要编译的源代码路径,这是一个数组。
3.include_dirs:表示编译过程中要用到的目录,这些目录中的头文件可以在预编译指令 #include 搜索到。在这里使用了一个比较特殊的写法,没有把路径用字符串常量给出,而是运行一个命令 node -e "require('nan')" ,nan库后面再说,先看看这个命令输出什么: node_modules\nan ,原来这句命令的意思是返回nan库的路径。
OK,既然已经配置了源代码是hello.cc,那就建立一个这样的文件。有一个问题需要提前提醒大家,我们所写的c++模块最终是要被v8引擎使用,所以api、写法等受到v8引擎的制约。而不同版本的nodejs其实采用的v8引擎的版本也不尽相同,这也就意味着很难用一套c++代码满足不同版本的nodejs(指编译过程,编译完成后跨版本应该能够使用,没有验证过。github不能上传二进制类库,所以github上开源会有麻烦。npm可以直接上传二进制类库,跳过编译步骤,所以问题相对较小)。
node 0.11及以上版本:
#include &node.h&
#include &v8.h&
using namespace v8;
void SleepFunc(const v8::FunctionCallbackInfo&Value&& args) {
& Isolate* isolate = Isolate::GetCurrent();
& HandleScope scope(isolate);
& double arg0 = args[0] -& NumberValue();
& Sleep(arg0);
void Init(Handle&Object& exports) {
& Isolate* isolate = Isolate::GetCurrent();
& exports-&Set(String::NewFromUtf8(isolate, "sleep"),
&&&&& FunctionTemplate::New(isolate, SleepFunc)-&GetFunction());
NODE_MODULE(hello, Init);
node 0.10及以下版本:
#include &node.h&
#include &v8.h&
using namespace v8;
Handle&Value& SleepFun(const Arguments& args) {
& HandleS&
& double arg0 = args[0] -& NumberValue();
& Sleep(arg0);
& return scope.Close(Undefined());
void Init(Handle&Object& exports) {
& exports-&Set(String::NewSymbol("sleep"),
&&&&& FunctionTemplate::New(SleepFun)-&GetFunction());
NODE_MODULE(hello, Init);
可以看出,变化还是相当大的,如果能屏蔽这些差异就太好了,有办法了?我写这么多还不就是想告诉你有办法。是时候请出nan库了。
还记得在binding.gyp中,我们引入nan库的路径,就是要在这里用。nan库是干嘛的呢?它提供了一层抽象,屏蔽了nodejs 0.8、nodejs 0.10、nodejs 0.12、io.js之前addon的语法差异。赞!
先安装: npm install --save nan ,看看同样的功能,用了nan后如何实现:
#include &nan.h&
using namespace v8;
NAN_METHOD(Sleep){
&&& NanScope();
&&& double arg0=args[0]-&NumberValue();
&&& Sleep(arg0);
&&& NanReturnUndefined();
void Init(Handle&Object& exports){
&&& exports-&Set(NanSymbol("sleep"), FunctionTemplate::New(Sleep)-&GetFunction());
NODE_MODULE(hello, Init);
你需要了解的就是nan这套东西,至于v8的那一套就可以不用关注。
从下往上看:
NODE_MODULE(hello, Init);
&这句定义addon的入口。注意第一个参数要与我们在binding.gyp中target_name一项一致。第二个参数就是addon的入口函数。
& 代码如下:
&void Init(Handle&Object& exports){
&&& exports-&Set(NanSymbol("sleep"), FunctionTemplate::New(Sleep)-&GetFunction());
&这段代码就是addon的入口方法。它接收两个参数,分别是exports和module。上面的示例省略了第二个参数。如果模块提供一个对象,可以像示例中那个,直接给exports指定要提供的key-value;如果特殊一点,仅提供一个数值,或一个函数,则需要用到第二个参数,类似于 NODE_SET_METHOD(module, "exports", foo); 。这个示例中是表示要输出这样一个模块:
&&& "sleep": Sleep
Sleep是一个函数,下来就来看看Sleep的定义:
NAN_METHOD(Sleep){
&&& NanScope();
&&& double arg0=args[0]-&NumberValue();
&&& Sleep(arg0);
&&& NanReturnUndefined();
其实就是读取javascript传入的参数,转成double型,再调用c++的sleep方法。
下面就要开始编译这个模块了。首先执行 node-gyp configure 来进行构建前准备工作,它会生成一个build文件夹和一些文件。接下来运行 node-gyp build 就可以开始编译了。在这个示例中,最终会在/build/Release/目录下生成一个hello.node文件,这就是最终能被javascript引用的addon模块了。
如果后续对c++代码有修改,就不用再运行 node-gyp configure ,直接运行 node-gyp build 就好。
nodejs使用
建立一个index.js,看看怎么用这个模块吧:
var sleep=require('./build/Release/hello.node').
console.log(new Date);
sleep(1000);
console.log(new Date);
// Wed Mar 04 :18 GMT+0800 (中国标准时间)
// Wed Mar 04 :19 GMT+0800 (中国标准时间)&&&&&&&
很容易吧,跟普通的javascript函数的使用方式一模一样。
至此本文想要分享的技术要点已经阐述完了。不过……究竟跟开篇提供的方法比起来有什么不一样?我不截图了,直接说明结果:
由于addon方式采用的方法是线程挂起,理论上不会有CPU占用和内存变化,结果也是验证了这一点。再看javascript循环模拟sleep的方式,因为一直在跑循环,内存增加一点可以理解,没什么大不了;再看CPU占用25%,似乎还算过得去。真的是这样吗?揭露真相的时候到了。我测试的笔记本电脑的CPU是双核四线程,再结合25%的CPU占用……难道双核四线程中有一个线程就被这个sleep给占用了?其实我发现这期间并没有一个线程被锁死,不过这不是javascript的功劳,而是intel超线程的功劳。因为说是四线程,其实本质是两个处理核心只能是双线程,只是cpu做了一个时间片切割上的小把戏。例如核心cpu01分成了t0和t2,假设在n tick(调度周期)后的一个tick内,任务会分到t0,那么在再后面一个tick,任务会分到t2。所以从一个比较长的时间尺度(相对于调度周期),一个任务在t0和t2上运行的时间基本是相当的。于是呈现出来的情景是nodejs的进程没有占用t0或t2到100%,而是分别占用了50%上下。由于windows的进程调度相对比较复杂,所以CPU占用量上下浮动很大。可以这样预测,如果是双核双线程的CPU来处理这个脚本,CPU占用会上升到50%,并且一个核心卡死。如果是单核CPU来处理,CPU一下子会上升到100%。
好像CPU这段说得有点多,超线程那些也是猜测,各位看看就好。
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 华为手机维修中心 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信