google v8使用示例

2023-10-27

概念解释
Handle
V8里使用Handle类型来托管 JavaScript对象,与C++的std::shared_pointer类似,Handle类型间的赋值均是直接传递对象引用,但不同的是,V8使用自己的GC来管理对象生命周期,而不是智能指针常用的引用计数。如果一个v8对象没有任何Handle与之相关联(不再被访问),那么这个对象很快就会被垃圾回收器回收掉。
Handle有两种类型,Local Handle和Persistent Handle,类型分别是Local : Handle和Persistent : Handle,前者和Handle没有区别,生存周期都在scope内。而后者的生命周期脱离scope,你需要手动调用Persistent::Dispose结束其生命周期。也就是说Local Handle相当于在C++在栈上分配对象,而Persistent Handle相当于C++在堆上分配对象。
 
Isolate
Isolate表示一个独立的v8引擎实例,每个实例维护不同的状态。一个Isolate中的对象不能在其他Isolate中使用。当v8被初始化的时候,一个默认isolate被默认创建。开发者可以通过创建额外的Isolate在多线程环境下并行使用。一个Isolate任意时间只允许一个线程在其中运行,可以使用Locker和Unlocker来进行多个线程对一个Isolate的同步。

Context
V8允许不同的JavaScript代码运行在完全不同的环境下,其运行环境称为Context。不同的Context下拥有自己的全局对象(PersistentHandle),运行代码时必须指定所在的Context。最典型的例子就是Chrome的标签,每个标签都拥有自己的Context。
Context拥有自己的全局代理对象(global proxy object),每个Context下的全局对象都是这个全局代理对象的属性。通过Context::Global ()可以得到这个全局代理对象。新建Context时你可以手动指定它的全局代理对象,这样每个Context都会自动拥有一些全局对象,比如DOM。
Context也是一种scope,通过Context::Enter ()和Context::Exit ()来进入、退出,或者使用类似于HandleScope的Context::Scope来隐式进入。

External
v8::External,它的作用是把C++的对象包装成Javascript中的变量。External::New接受一个C++对象的指针作为初始化参数,然后返回一个包含这个指针的Handle对象供v8引擎使用。在使用这个Handle对象时可以通过External::Value函数来得到C++对象的指针。
Template
Template是介于Javascript和C++变量间的中间层,你首先由C++对象生成一个Template,然后再由Template生成Javascript函数的对象。你可以事先在Template中准备好一些预备属性,然后生成的Javascript对象都将具备这些属性。
 
FunctionTemplate
你可以使用FunctionTemplate::New ()生成一个空函数,然后用FunctionTemplate::SetCallHandler ()将其和C++函数绑定,或者直接靠FunctionTemplate::New (InvocationCallback callback)来用C++函数初始化一个FunctionTemplate。
用来生成FunctionTemplate的C++函数必须满足InvocationCallback的条件,即函数签名必须如下:
  1. typedef Handle<Value> (*InvocationCallback)(const Arguments& args);
如果是简单给js脚本使用,创建并设置完FunctionTemplate就可以了;但是如果在c++中使用FunctionTemplate或者是需要为Function设置一些属性字段的话,需要从FunctionTemplate通过GetFunction()来创建一个Function。
此后,你可以使用FunctionTemplate::GetFunction()来获取对应的v8::Function。但是一个FunctionTemplate只能生成一个Function,FunctionTemplate::GetFunction()返回的都是同一个实体。这是因为Javascript里显式声明的全局函数只有一个实例。
Javascript常用new Function ();的形式来创建对象,而C++中,Function::NewInstance可以返回一个函数的Instance。你可以使用Function::NewInstance返回一个函数对象,等同于Javascript中的var tmp = new func;。
ObjectTemplate
ObjectTemplate的目的就是根据包装起来的C++对象生成v8::Object。接口与Template也大致相当,通过ObjectTemplate::New返回新的ObjectTemplate,通过ObjectTemplate::NewInstance。ObjectTemplate提供了一种Internal Field,也就是内部储存空间,我们可以通过External类型把C++对象储存在ObjectTemplate中。
建立了ObjectTemplate后,我们可以通过ObjectTemplate::SetInternalFieldCount设定内部储存多少个内部变量。然后通过ObjectTemplate::NewInstance建立新的Object,再在v8::Object中通过SetInternalField来对内部变量进行操作。
Accessors的实现原理就是为Object绑定一个C++对象,并为其在全局代理对象中设置一个名字,当JavaScript按指定的名字访问Object的时候,调用Getter和Setter函数来访问C++对象数据。
 
>>> 如果需要在Function中创建一个Function,处理一个C++对象。首先需要将这个C++对象使用SetInnerField封转到一个Object中;其次在FunctionTemplate::New的时候,将Object作为data参数传入New函数,这样在创建的Function中就可以通过args.Data()获取到之前的Object了(Value类型的,使用ToObject转成Object类型),然后通过GetPointerFromInnerField就可以获得之前的C++对象了。
示例代码
直接上代码
  1. #include <string>
  2. #include <cstring>

  3. #include <sys/time.h>

  4. #include <v8.h>

  5. using namespace v8;

  6. #ifndef THREAD_NUM
  7. #define THREAD_NUM 4
  8. #endif

  9. #ifndef DEF_CALLS
  10. #define DEF_CALLS 100000
  11. #endif

  12. #ifdef NO_LOG

  13. #define CDEBUG_LOG(format, args...) 
  14. #define CTRACE_LOG(format, args...) 
  15. #define CWARNING_LOG(format, args...) 
  16. #define CFATAL_LOG(format, args...) 

  17. #else

  18. #define CDEBUG_LOG(format, args...) \
  19.     do{\
  20.          char tmpstr[65536];\
  21.          snprintf(tmpstr,65535,format,##args);\
  22.          printf("[thread:%u] %s\n", pthread_self(), tmpstr); \
  23.     }while(0)
  24. #define CTRACE_LOG(format, args...) \
  25.     do{\
  26.          char tmpstr[65536];\
  27.          snprintf(tmpstr,65535,format,##args);\
  28.          printf("[thread:%u] %s\n", pthread_self(), tmpstr); \
  29.     }while(0)
  30. #define CWARNING_LOG(format, args...) \
  31.     do{\
  32.          char tmpstr[65536];\
  33.          snprintf(tmpstr,65535,format,##args);\
  34.          printf("[thread:%u] %s\n", pthread_self(), tmpstr); \
  35.     }while(0)
  36. #define CFATAL_LOG(format, args...) \
  37.     do{\
  38.          char tmpstr[65536];\
  39.          snprintf(tmpstr,65535,format,##args);\
  40.          printf("[thread:%u] %s\n", pthread_self(), tmpstr); \
  41.     }while(0)

  42. #endif

  43. static Handle<Value> IntGetter(Local<String>name, const AccessorInfo &info)
  44. {
  45.     String::Utf8Value utf8_value_name(name);
  46.     std::string key(*utf8_value_name);
  47.     const char * strKey = key.c_str();

  48.     if(strcmp(strKey, "c"))
  49.     {
  50.         return Int32::New(3);
  51.     }
  52.     else if(strcmp(strKey, "d"))
  53.     {
  54.         return Int32::New(4);
  55.     }

  56.     return Int32::New(1);
  57. }

  58. static Handle<Value> NamedGetter(Local<String>name, const AccessorInfo &info)
  59. {
  60.     String::Utf8Value utf8_value_name(name);
  61.     std::string key(*utf8_value_name);
  62.     const char * strKey = key.c_str();

  63.     if(strcmp(strKey, "f1"))
  64.     {
  65.         return Int32::New(5);
  66.     }
  67.     else if(strcmp(strKey, "f2"))
  68.     {
  69.         return Int32::New(6);
  70.     }

  71.     return Int32::New(1);
  72. }

  73. static Handle<Value> IndexedGetter(uint32_t index, const AccessorInfo &info)
  74. {
  75.     if(index==1)
  76.         return Int32::New(7);
  77.     else if(index==2)
  78.         return Int32::New(8);

  79.     return Int32::New(1);
  80. }

  81. static Handle<Value> Sum(const Arguments &args)
  82. {
  83.     if(args.Length()!=2)
  84.         return Undefined();
  85.     if(args[0]->IsInt32() && args[1]->IsInt32())
  86.         return Int32::New(args[0]->Int32Value()+args[1]->Int32Value());
  87.     else
  88.         return Undefined();
  89. }

  90. void *v8_func_op(void *)
  91. {
  92.     int count = 0;
  93.     struct timeval tvStart;
  94.     struct timeval tvEnd;
  95.     // Create a stack-allocated handle scope.
  96.     HandleScope handle_scope;

  97.     // Create a ObjectTemplate
  98.     Handle<ObjectTemplate> global = ObjectTemplate::New();
  99.     //Function Set before Context::New
  100.     global->Set(String::New("Sum"), FunctionTemplate::New(Sum));

  101.     Persistent<Context> context = Context::New(NULL, global);
  102.     // Create a new context.
  103.     //Persistent<Context> context = Context::New();
  104.     Context::Scope context_scope(context);

  105.     //Sum(1,2);
  106.     //*
  107.     (void) gettimeofday(&tvStart, NULL);
  108.     for(int i=0; i<DEF_CALLS; i++)
  109.     {
  110.         // Create a stack-allocated handle scope.
  111.         HandleScope handle_subscope;

  112.         const char *JS_STR = "Sum(1,1)";
  113.         Handle<String> source = String::New( JS_STR );
  114.         Handle<Script> script = Script::Compile(source);

  115.         // Run the script to get the result.
  116.         TryCatch trycatch;
  117.         Handle<Value> result = script->Run();
  118.         if(result.IsEmpty())
  119.         {
  120.             Handle<Value> exception = trycatch.Exception();
  121.             String::AsciiValue exception_str(exception);
  122.             printf("Exception: %s\n", *exception_str);
  123.         }
  124.         else
  125.         {
  126.             if(result->IsInt32())
  127.             {
  128.                 CDEBUG_LOG("JS RET: %d", result->Int32Value());
  129.             }
  130.             else
  131.             {
  132.                 CDEBUG_LOG("JS FAILED");
  133.             }
  134.         }
  135.     }
  136.     (void) gettimeofday(&tvEnd, NULL);
  137.     fprintf(stdout, "[thread:%u] %u calls - timespan : %lu us\n", pthread_self(), DEF_CALLS, (tvEnd.tv_sec-tvStart.tv_sec)*1000000+(tvEnd.tv_usec-tvStart.tv_usec));
  138.     usleep(2000);
  139.     //*/
  140.     
  141.     //1+1==2
  142.     //*
  143.     (void) gettimeofday(&tvStart, NULL);
  144.     for(int i=0; i<DEF_CALLS; i++)
  145.     {
  146.         // Create a stack-allocated handle scope.
  147.         HandleScope handle_subscope;

  148.         const char *JS_STR = "1+1==2";
  149.         Handle<String> source = String::New( JS_STR );
  150.         Handle<Script> script = Script::Compile(source);

  151.         // Run the script to get the result.
  152.         TryCatch trycatch;
  153.         Handle<Value> result = script->Run();
  154.         if(result.IsEmpty())
  155.         {
  156.             Handle<Value> exception = trycatch.Exception();
  157.             String::AsciiValue exception_str(exception);
  158.             printf("Exception: %s\n", *exception_str);
  159.         }
  160.         else
  161.         {
  162.             if(result->IsBoolean())
  163.             {
  164.                 if(result->BooleanValue())
  165.                 {
  166.                     CDEBUG_LOG("JS RET: TRUE");
  167.                 }
  168.                 else
  169.                 {
  170.                     CDEBUG_LOG("JS RET: FALSE");
  171.                 }
  172.             }
  173.             else
  174.             {
  175.                 CDEBUG_LOG("JS FAILED");
  176.             }
  177.         }
  178.     }
  179.     (void) gettimeofday(&tvEnd, NULL);
  180.     fprintf(stdout, "[thread:%u] %u calls - timespan : %lu us\n", pthread_self(), DEF_CALLS, (tvEnd.tv_sec-tvStart.tv_sec)*1000000+(tvEnd.tv_usec-tvStart.tv_usec));
  181.     usleep(2000);
  182.     //*/

  183.     //static set: a+b
  184.     //*
  185.     context->Global()->Set(String::New("a"), Int32::New(1));
  186.     context->Global()->Set(String::New("b"), Int32::New(2));

  187.     (void) gettimeofday(&tvStart, NULL);
  188.     for(int i=0; i<DEF_CALLS; i++)
  189.     {
  190.         // Create a stack-allocated handle scope.
  191.         HandleScope handle_subscope;

  192.         const char *JS_STR = "a+b";
  193.         Handle<String> source = String::New( JS_STR );
  194.         Handle<Script> script = Script::Compile(source);

  195.         // Run the script to get the result.
  196.         TryCatch trycatch;
  197.         Handle<Value> result = script->Run();
  198.         if(result.IsEmpty())
  199.         {
  200.             Handle<Value> exception = trycatch.Exception();
  201.             String::AsciiValue exception_str(exception);
  202.             printf("Exception: %s\n", *exception_str);
  203.         }
  204.         else
  205.         {
  206.             if(result->IsInt32())
  207.             {
  208.                 CDEBUG_LOG("JS RET: %d", result->Int32Value());
  209.             }
  210.             else
  211.             {
  212.                 CDEBUG_LOG("JS FAILED");
  213.             }
  214.         }
  215.     }
  216.     (void) gettimeofday(&tvEnd, NULL);
  217.     fprintf(stdout, "[thread:%u] %u calls - timespan : %lu us\n", pthread_self(), DEF_CALLS, (tvEnd.tv_sec-tvStart.tv_sec)*1000000+(tvEnd.tv_usec-tvStart.tv_usec));
  218.     usleep(2000);
  219.     //*/

  220.     //static accessor: c+d
  221.     //*
  222.     context->Global()->SetAccessor(String::New("c"), IntGetter);
  223.     context->Global()->SetAccessor(String::New("d"), IntGetter);

  224.     (void) gettimeofday(&tvStart, NULL);
  225.     for(int i=0; i<DEF_CALLS; i++)
  226.     {
  227.         // Create a stack-allocated handle scope.
  228.         HandleScope handle_subscope;

  229.         const char *JS_STR = "c+d";
  230.         Handle<String> source = String::New( JS_STR );
  231.         Handle<Script> script = Script::Compile(source);

  232.         // Run the script to get the result.
  233.         TryCatch trycatch;
  234.         Handle<Value> result = script->Run();
  235.         if(result.IsEmpty())
  236.         {
  237.             Handle<Value> exception = trycatch.Exception();
  238.             String::AsciiValue exception_str(exception);
  239.             printf("Exception: %s\n", *exception_str);
  240.         }
  241.         else
  242.         {
  243.             if(result->IsInt32())
  244.             {
  245.                 CDEBUG_LOG("JS RET: %d", result->Int32Value());
  246.             }
  247.             else
  248.             {
  249.                 CDEBUG_LOG("JS FAILED");
  250.             }
  251.         }
  252.     }
  253.     (void) gettimeofday(&tvEnd, NULL);
  254.     fprintf(stdout, "[thread:%u] %u calls - timespan : %lu us\n", pthread_self(), DEF_CALLS, (tvEnd.tv_sec-tvStart.tv_sec)*1000000+(tvEnd.tv_usec-tvStart.tv_usec));
  255.     usleep(2000);
  256.     //*/

  257.     //named property: e.f1+e.f2
  258.     //*
  259.     Handle<ObjectTemplate> named = ObjectTemplate::New();
  260.     named->SetNamedPropertyHandler(NamedGetter, NULL);
  261.     context->Global()->Set(String::New("e"), named->NewInstance());

  262.     (void) gettimeofday(&tvStart, NULL);
  263.     for(int i=0; i<DEF_CALLS; i++)
  264.     {
  265.         // Create a stack-allocated handle scope.
  266.         HandleScope handle_subscope;

  267.         const char *JS_STR = "e.f1+e.f2";
  268.         Handle<String> source = String::New( JS_STR );
  269.         Handle<Script> script = Script::Compile(source);

  270.         // Run the script to get the result.
  271.         TryCatch trycatch;
  272.         Handle<Value> result = script->Run();
  273.         if(result.IsEmpty())
  274.         {
  275.             Handle<Value> exception = trycatch.Exception();
  276.             String::AsciiValue exception_str(exception);
  277.             printf("Exception: %s\n", *exception_str);
  278.         }
  279.         else
  280.         {
  281.             if(result->IsInt32())
  282.             {
  283.                 CDEBUG_LOG("JS RET: %d", result->Int32Value());
  284.             }
  285.             else
  286.             {
  287.                 CDEBUG_LOG("JS FAILED");
  288.             }
  289.         }
  290.     }
  291.     (void) gettimeofday(&tvEnd, NULL);
  292.     fprintf(stdout, "[thread:%u] %u calls - timespan : %lu us\n", pthread_self(), DEF_CALLS, (tvEnd.tv_sec-tvStart.tv_sec)*1000000+(tvEnd.tv_usec-tvStart.tv_usec));
  293.     usleep(2000);
  294.     //*/
  295.     
  296.     //indexed property: f[1]+f[2]
  297.     //*
  298.     Handle<ObjectTemplate> indexed = ObjectTemplate::New();
  299.     indexed->SetIndexedPropertyHandler(IndexedGetter, NULL);
  300.     context->Global()->Set(String::New("f"), indexed->NewInstance());

  301.     (void) gettimeofday(&tvStart, NULL);
  302.     for(int i=0; i<DEF_CALLS; i++)
  303.     {
  304.         // Create a stack-allocated handle scope.
  305.         HandleScope handle_subscope;

  306.         const char *JS_STR = "f[1]+f[2]";
  307.         Handle<String> source = String::New( JS_STR );
  308.         Handle<Script> script = Script::Compile(source);

  309.         // Run the script to get the result.
  310.         TryCatch trycatch;
  311.         Handle<Value> result = script->Run();
  312.         if(result.IsEmpty())
  313.         {
  314.             Handle<Value> exception = trycatch.Exception();
  315.             String::AsciiValue exception_str(exception);
  316.             printf("Exception: %s\n", *exception_str);
  317.         }
  318.         else
  319.         {
  320.             if(result->IsInt32())
  321.             {
  322.                 CDEBUG_LOG("JS RET: %d", result->Int32Value());
  323.             }
  324.             else
  325.             {
  326.                 CDEBUG_LOG("JS FAILED");
  327.             }
  328.         }
  329.     }
  330.     (void) gettimeofday(&tvEnd, NULL);
  331.     fprintf(stdout, "[thread:%u] %u calls - timespan : %lu us\n", pthread_self(), DEF_CALLS, (tvEnd.tv_sec-tvStart.tv_sec)*1000000+(tvEnd.tv_usec-tvStart.tv_usec));
  332.     usleep(2000);
  333.     //*/
  334.     
  335.     //Should Call GC
  336.     V8::IdleNotification();
  337.     V8::LowMemoryNotification();
  338.     V8::ContextDisposedNotification();

  339.     //Heap Statis
  340.     {
  341.         HeapStatistics hs;
  342.         V8::GetHeapStatistics(&hs);
  343.         fprintf(stderr, "[thread:%u] "
  344.                 "total_heap_size:%u "
  345.                 "total_heap_size_executable:%u "
  346.                 "used_heap_size:%u "
  347.                 "heap_size_limit:%u\n",
  348.                 pthread_self(),
  349.                 hs.total_heap_size(),
  350.                 hs.total_heap_size_executable(),
  351.                 hs.used_heap_size(),
  352.                 hs.heap_size_limit());
  353.     }

  354.     // Dispose the persistent context.
  355.     context.Dispose();
  356.     context.Clear();

  357.     //return 0;
  358.     return NULL;
  359. }

  360. void * v8_func(void *)
  361. {
  362.     //One thread have an isolate
  363.     v8::Isolate* isolate = v8::Isolate::New();
  364.     {
  365.         Locker locker(isolate);
  366.         v8::Isolate::Scope iscope(isolate);

  367.         //*
  368.         {
  369.             ResourceConstraints rc;
  370.             rc.set_max_young_space_size(2048); //KB
  371.             rc.set_max_old_space_size(10); //MB
  372.             rc.set_max_executable_size(10); //MB
  373.             rc.set_stack_limit(reinterpret_cast<uint32_t*>((char*)&rc- 1024 * 400));

  374.             SetResourceConstraints(&rc);
  375.         }
  376.         //*/

  377.         v8_func_op(NULL);
  378.     }

  379.     isolate->Dispose();

  380.     return NULL;
  381. }

  382. int main(int argc, char *argv[])
  383. {
  384. #define MAX_THREAD_NUM 120
  385.     pthread_t pid[MAX_THREAD_NUM] = {0};
  386.     void * res = NULL;
  387.     int thread_num = THREAD_NUM;

  388.     V8::SetFlagsFromCommandLine(&argc, argv, true); 

  389.     for(int i=0; i<thread_num; i++)
  390.         pthread_create(&pid[i], NULL, v8_func, NULL);

  391.     for(int i=0; i<thread_num; i++)
  392.         pthread_join(pid[i], &res);

  393.     return 0;
  394. }
参考
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

google v8使用示例 的相关文章

  • engine.io 与 socket.io 有何不同?

    LearnBoost 似乎有一个新项目叫做引擎 io https github com LearnBoost engine io理论上似乎与socket io 类似 1 在什么情况下您会使用其中一种而不是另一种 2 对于需要通过node j
  • require('babel/register') 不起作用

    我在客户端上有一个用 ES6 编写的同构应用程序Babel 转译器 http babeljs io 我希望我的 Express 服务器具有与客户端代码相同的 ES6 语法 很遗憾require babel register 不起作用 服务器
  • 如何在express中设置单个会话maxAge?

    据我了解 您可以在启动应用程序时设置 maxAge 如下所示 connect session secret keyboard cat cookie maxAge 60000 但是 我想实现一些类似于 记住我 设置的东西 我该怎么做呢 多谢
  • 如何对 NestJS 中的控制器应用防护进行单元测试?

    我在 NestJS 中配置了一个控制器 我想检查是否设置了适当的防护 有人有如何完成此操作的示例吗 这个 删节的 示例作为一个应用程序可以正常工作 所以我只是在测试指导之后 您会注意到在用户测试中有一些我正在调用的测试Reflect get
  • 在 Node.js 中包含另一个文件中的 JavaScript 类定义

    我正在为 Node js 编写一个简单的服务器 并且使用我自己的类 名为User看起来像 function User socket this socket socket this nickname null just the typical
  • mocha.opts 已弃用,如何迁移到 package.json?

    我正在开发一个大型项目 自从上周我更新了摩卡以来 现在我们收到警告 DeprecationWarning 通过 mocha opts 进行的配置已被弃用并且 将从 Mocha 的未来版本中删除 使用 RC 文件或 改为 package js
  • 如何使用 Node.js 解析 JSON? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我应该如何使用 Node js 解析 JSON 是否有一些模块可以安全地验证和解析 JSON 你可以简单地使用JSON parse h
  • 使用mockery和sinon模拟类方法

    我正在学习使用带有 sinon 的节点模块模拟进行单元测试 仅使用模拟和普通类 我就可以成功注入模拟 不过 我想注入一个 sinon 存根而不是一个普通的类 但我在这方面遇到了很多麻烦 我试图嘲笑的班级 function LdapAuth
  • 电子邮件模板中的剪贴板功能

    我想在电子邮件模板中发送优惠券代码 一个小按钮 用于复制剪贴板上输入元素的内容 通过电子邮件模板 我的意思是我想发送一封电子邮件 其中包含优惠券代码 并且电子邮件模板中会有一个按钮 允许我将其复制到剪贴板 这可以做到吗 任何帮助将不胜感激
  • 使用 Node.js 访问用 C++ 编写的 SDK

    我有一个用 C 语言编写的 SDK 可以与我的扫描仪设备进行通信 我需要开发一个可以访问扫描仪设备的电子应用程序 我知道有很多库可用于扫描仪 但我想使用这个 SDK 因为它允许我访问设备的完整功能 而且它是由设备制造商提供的 那么 有没有什
  • AWS Lambda 上的 NodeJS 集群

    是否可以在 lambda 函数中使用 cluster 模块 我试过这个 use strict var cluster require cluster var http require http var os require os var n
  • sails.js 水线嵌套填充查询

    我有一个返回对象的多个结果的查找查询 该对象包含一个包含另一个模型的模型 问题是水线不支持嵌套填充 因此它填充第一个模型 但不填充它的内部模型 我见过的所有示例都是针对 findOne 查询的 我正在寻找一种方法来解决返回多个结果的查找查询
  • 阻止 Mongoose 为子文档数组项创建 _id 属性

    如果您有子文档数组 Mongoose 会自动为每个子文档创建 id 例子 id mainId subDocArray id unwantedId field value id unwantedId field value 有没有办法告诉 M
  • ER_ACCESS_DENIED_ERROR:用户 ''@'localhost' 的访问被拒绝(使用密码:NO)

    我有这个问题 我已经研究过但无法解决它 我想它与数据库权限有关 但我无法修复它 if error throw error Error ER ACCESS DENIED ERROR Access denied for user localho
  • Excel Add In - console.log 在哪里输出它的消息 - NodeJS

    我正在尝试使用 JavaScript API 创建 Excel 插件 但我不明白 console log 在哪里输出它们的消息 所有 Microsoft 文档都包含 console log 示例 但没有解释 console log 输出消息
  • Node.js 中的 Twilio 短信回复

    我正在使用 node js 中的 twilio 编写移动通知系统 目前可以向用户发送短信 但我希望用户能够回复我 我需要收集用户发送文本的电话号码以及消息的内容 以查询我的 mongoosedb 我找不到太多这方面的信息 因此非常感谢您的帮
  • 如何在浏览器同步中配置端口

    我有一个gulp任务运行于browser sync 默认情况下它运行在node js服务器的端口3000上 我想将默认端口更改为任何其他端口 例如3010 var gulp require gulp connect require gulp
  • 从 Node.js 调用 execl、execle、execlp、execv、execvP 或 execvp 的方法

    POSIX 系统公开了一系列exec函数 允许人们将可能不同的东西加载到当前进程中 保留打开的文件描述符 进程标识符等 可以出于多种原因执行此操作 在我的情况下 这是引导 我想更改我自己的进程的命令行选项 然后在现有进程上重新加载它 这样就
  • NodeJS os 模块无法使用 userInfo()

    https nodejs org api os html os os userinfo options https nodejs org api os html os os userinfo options 节点版本 v4 2 6 NPM版
  • GraphQL - POST 正文丢失。您忘记使用 body-parser 中间件了吗?

    我的电脑上不断出现以下错误graphql查询但不确定原因 POST body missing Did you forget use body parser middleware 我在这里做了什么奇怪的事吗 我已经尝试了在线 body par

随机推荐

  • Mac苹果电脑思维导图Xmind 2022中文

    Xmind 2022中文是一款全新的思维导图软件 它具有新主题 其中一些具有更柔和的色调 以提供更现代的外观 它的独特功能是 禅宗模式 它将自动隐藏额外的面板 使您可以专注于自己的想法并添加到文档中 而不会分心 不管是UI界面设计还是性能都
  • 又一次自己编译Mono,这次是在Windows上,玩Bundle

    成功 又一次自己编译Mono 这次是在Windows上 玩Bundle 作者 V君 发布于 2017 10 30 21 07 Monday 分类 折腾手记 目标 将 net 应用程序用只用一个 exe 承载 并极大缩减体积 且能保证工作正常
  • Ansible的基础了解

    目录 第一章 Ansible概述 1 1 Ansible是什么 1 2 Ansible的特性和过程 1 3 ansible 具有如下特点 1 4 Ansible的四个组件 1 5 ansible 核心程序 1 6 ansible执行的过程
  • DevOps面试问题

    DevOps是一组过程 方法与系统的统称 用于促进开发 应用程序 软件工程 技术运营和质量保障 QA 部门之间的沟通 协作与整合 下面为大家分享DevOps系列的面试问题 持续整合问题 问题一 持续集成是什么意思 我将建议您通过给出持续集成
  • opencv分水岭算法分割硬币

    网上有Python写的 但是没有C 写的 所以自己搞了个 东拼西凑的结果 毕竟我也不是大神 凑活着看吧 倾情奉献 欢迎指教 include
  • H264码流RTP封装方式详解:rfc3984

    264码流RTP封装方式详解 文章目录 H264码流RTP封装方式详解 1 H264基本概念 2 NALU Header介绍 3 RTP封装H264码流 3 1 单一NALU模式 3 2 组合帧封装模式 3 3 分片封装模式 4 代码解析
  • Android多屏幕适配学习笔记

    http blog csdn net a220315410 article details 9139397
  • C++57个入门知识点_21_ 析构函数的调用(主程序结束前自动跳入对象析构函数,析构函数中使用free()函数就可实现对象资源的释放;内存泄漏:内存没有得到释放;不指定大小的数组定义方法:指针)

    上两篇C 57个入门知识点 19 构造函数的作用及写法 作用 用于对象初始化 定义时候就定义对象初值 写法 函数名是类名 不写函数返回值 参数可以有也可以没有 使用 CStudent stu 张三 C 57个入门知识点 20 构造函数的调用
  • 常用hadoop dfs命令

    创建目录 hadoop dfs mkdir home 上传文件或目录到hdfs hadoop dfs put hello hadoop dfs put hellodir 查看目录 hadoop dfs ls 创建一个空文件 hadoop d
  • 设计模式的设计原则

    为什么需要设计模式 我的理解设计模式就是一种针对某种问题的套路 是一套被反复使用 多数人所知晓的 经过分类编目的 代码设计经验的总结 1 开闭原则 1 1 定义 一个软件实体应当对扩展开放 对修改关闭 即软件实体应尽量在不修改原有代码下进行
  • gcc4.9 编译stdatomic.h 异常

    使用了 include
  • word总页数不包含封面_明明封面没有设置页码,但总页码为啥总是多一页?

    先别着急关掉 既然你点进来了 说明你曾经也遇到过这样的情况或者你正被Word文档的页码设置折磨着 你们的痛苦我都懂 我也曾被页码设置按在地上来回摩擦 甚至会有直接手动输入页码的冲动 不过你看过了这篇文章就不会再有标题中的困扰了 我们今天就来
  • php webscokt_websocket(示例php实现)

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议 在 WebSocket API 中 浏览器和服务器只需要做一个握手的动作 然后 浏览器和服务器之间就形成了一条快速通道 两者之间就直接可以数据互相
  • USB总线电平标准、USB总线状态、USB总线信号详解

    来自 https hellocode blog csdn net article details 113639911 一 USB总线电平标准 USB总线电平标准如下 下图标识了低速 全速 高速总线输出特性的电平标准 二 USB总线状态 下图
  • 一个40岁老码农的总结,奋斗没有意义,选择大于努力(zz)

    一个40岁老码农的总结 奋斗没有意义 选择大于努力 转载 你的努力为什么没有意义 今年刚好 40 岁 在一家著名外企做到技术专家的位置 在亲戚朋友眼中 俨然已算半个 成功人士 但内心深处 却无一刻不战战兢兢 我知道 自己就像一个风雨中的高跷
  • Matlab基本操作和矩阵输入(郭彦甫视频学习笔记)

    who whos 查看工作区当前变量 clear 清空工作区的所有变量 慎用 clear valuable 清除变量valuable clc 清空命令行窗口 clear all 清除工作区所有变量 close all 关闭所有显示的图片 一
  • Android. 解决依赖冲突 Program type already present

    目录 常用引用 解决方案 在实际开发中 为了提高开发速度和效率 避免不了引用第三方提供的依赖和类库 如果含有相同依赖的类库被我们引用时 而他们的版本又不相同 就有可能会导致一系列问题和异常 常用引用 网络相关 okhttp retrofit
  • OpenCV使用CMake和MinGW的编译安装及其在Qt配置运行

    前言 本篇博文是使用 32 位的 MinGW 在 Windows 下编译 OpenCV 生成 32 位的 dll 关于使用 64 位的 MinGW 编译 OpenCV 生成 64 位的 dll 见 OpenCV使用CMake和MinGW w
  • Spark基础概念

    概念 Spark 提供了一个全面 统一的框架用于管理各种有着不同性质 文本数据 图表数据等 的数据集和数据源 批量数据或实时的流数据 的大数据处理的需求 核心架构 Spark Core 包含Spark 的基本功能 尤其是定义RDD 的API
  • google v8使用示例

    概念解释 Handle V8里使用Handle类型来托管 JavaScript对象 与C 的std shared pointer类似 Handle类型间的赋值均是直接传递对象引用 但不同的是 V8使用自己的GC来管理对象生命周期 而不是智能