Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all 14821 articles
Browse latest View live

为了学习 flutter, 所以借用 cnode api, 写了个 flutter 的cnode android客户端~

$
0
0

flutter cnode android 客户端

最近在学习flutter, 但是光看文档感觉有点枯燥而且也没有直观的感受 所以借用 cnode 的open api 写了个客户端, 加深下理解 客户端功能不多, 但还是欢迎大家能试用下哈

下载地址

image.png

  • 64位

image.png

  • 32 位

真机运行图

  • 75A330504A80DF39FF0808EB4FB7E0F1.jpg
  • 66E9070BCAF52370CF45A6D35243D270.jpg
  • 8F41E1E3AA5B0FC616C0C570A8441AA3.jpg

源码地址

@hello_cnode

感谢 cnode open api


package.json的疑问

$
0
0

我有一个package.json的文件. scripts部分的缩进是6个空格 在linux上面通过git拉取代码下来,进行npm install变为了4个空格的缩进。 npm install之前 image.pngnpm install之后

image.png

我的依赖项

"dependencies": {
    "@grpc/proto-loader": "^0.5.3",
    "amqplib": "^0.5.5",
    "async": "^3.1.0",
    "dateformat": "^3.0.3",
    "grpc": "^1.24.2",
    "ioredis": "^4.14.1",
    "md5": "^2.2.1",
    "mongodb": "^3.4.0",
    "mysql": "^2.17.1",
    "request": "^2.88.0"
  }

翻了下文档和npm install部分源码我发现fs模块只有执行过读文件操作,并没有写(或许我忽略了)。

请问各位这是什么原因导致格式化?

请教一个下载图片的问题

$
0
0

项目中有一个下载图片的需求,现在在编写下载代码的过程中遇到了一些问题。

我的需求是进行批量下载,如果下载失败需要进行记录,然后用本地的404图片替代。 下载完的图片需要马上放入docx文件中,所以需要对下载的过程进行整体阻塞。

一开始我是使用最简单的方法进行下载

function download(src, dest) {
	return new Promise((res,rej) => {
		const pipe = request(src).pipe(fs.createWriteStream(dest))
		pipe.on('close',() => res());
		pipe.on('error',(err) => rej(err));
	});
}

后面我发现, 如果目标是404的话,他会将404的信息写入到图片中,而不会有报错信息。 我的代码变成 request.get({url}, (err,res) => { if(err) return rej(err); if(res.statusCode === 404) return rej(‘404’); fs.writeFile(dest, responseBody, ‘binary’, err => { if(err) return rej(err); return res(1); }); }); 但组长说得使用流的方式写, 不然占用太多内存。 我又使用了wget,但是写完了之后发现偶尔会有一两张下载不完全,导致后面代码获取的时候出错。 查看了一下wget的代码,

    var downloader = new EventEmitter(),
    req = request(options, function(res) {
        var fileSize, writeStream, downloadedSize;
        if (res.statusCode === 200) {
            downloadedSize = 0;
            fileSize = res.headers['content-length'];
            writeStream = fs.createWriteStream(output, {
                flags: 'a',
                encoding: 'binary'
            });

            res.on('error', function(err) {
                writeStream.end();
                downloader.emit('error', err);
            });
            res.on('data', function(chunk) {
                downloadedSize += chunk.length;
                downloader.emit('progress', downloadedSize/fileSize);
                writeStream.write(chunk);
            });
            res.on('end', function() {
                writeStream.end();
                downloader.emit('end', output);
            });
        } else {
            downloader.emit('error', 'Server respond ' + res.statusCode);
        }
    });

我的代码里是用 downloader.on(‘end’,() => res());来判断是否成功, 但是在res.on(‘end’)的方法里面,writeStream.end();结束写入了,但好像还没有彻底完成? 所以我决定这样写

downloader.on('end',async () =>{
	await sleep(500);
	return res();
});

发现问题解决, 但是组长说不能这么写。

所以我又开始考虑superagent 我尝试是这么写

request.get(src)
	.ok(res => res.statusCode === 200)
	.then(res => {
		const pipe = res.pipe(writeStream);
		pipe.on....
	})

但是这里报错,显示 end() has already been called, so its too late to starting piping

那么现在问题来了, 怎样才能在判断了statusCode 的情况下使用流下载图片啊

express+vue部署到服务器怎么弄

$
0
0

express+vue部署到服务器怎么弄 求详细的教程

【深圳南山】一个小小的链接带您走进新锐雇主 AfterShip !

$
0
0

大家常言干啥都要带个图,无图言 X。既然如此,为了让大家真正了解一下我司,我们诚心诚意地拍摄了如下一支视频走进 AfterShip,希望看完可以给到大家一些惊喜!

我们招聘是真心的,想邀请你加入我们也是诚心的,ball ball 大家看在我们的诚意上点开一哈下面的链接瞧瞧我们吧,你一定不会后悔!

https://mp.weixin.qq.com/s/CqPaNJpIHYfgBolU6y1ekA

Node.js 后台工程师 12-23k

高级 Node.js 后台工程师 25-35k

Golang 后台工程师 15-25k

Java 开发工程师 15-25k

Java 开发工程师-大数据方向 15-25k

PHP 工程师 15-25k

React.js 前端工程师 12-23k

高级 React.js 前端工程师 25-35k

大数据开发工程师 DBA 18-35k

运维工程师 15-25k

Python 工程师 15-25k

高级 Python 工程师 25-35k

同时我们还有产品经理、HR 等岗位正在招聘!您可以直接到我们的官网 https://hr.aftership.com查看详情!

或者您可以将您的简历以 [姓名+应聘职位+论坛名称+日期] 为名的邮件发送到 qs.jin@aftership.com来与 HR 更直接的沟通!

AfterShip 办公室全新换代升级!与你在达实大厦 40 层相约!最顶尖的技术水平应当有最高层视野!

有关 AfterShip

AfterShip (爱客科技)( https://www.aftership.com/)是一个为国际性电商企业而设的 B2B SaaS 平台,通过提供全方位和全自动化的工具,帮助电商降低营运成本及实现智能营销。公司全自动化系统涵盖市场推广、订单管理、运单打印、快递跟踪及退换货管理等。

2012 年成立于香港,2014 年开始盈利,业务遍布全球,与全球 500 多家物流公司达成合作,涉及 30 多种主流语言业务体系。客户有 Amazon, Wish, eBay, Paypal, Groupon, Etsy,及各大小电商超过 100,000 家,是国际快递查询领域里面的龙头企业。

AfterShip 是一家以产品为驱动,技术为核心的公司,日均承担过亿 API 请求。从公司成立开始,便大量使用优秀开源系统,拥抱创新科技,公司有良好的 SaaS 付费习惯,浓厚的工具化文化。

AfterShip 注重人才培养,在这里工作,每个人都可参加从用户沟通、需求讨论、产品开发、到上线部署的环节 ,团队国际化,公司成员来自十个不同的国家。

戳这里看看用一个开源项目做的代码风格的公司介绍: https://activity.lagou.com/gracie/pc/AfterShip0213.html

AfterShip 是香港早期 Google Cloud Platform ( GCP ) 客户之一,并且成为香港第一家 GCP 案例分析的公司,正是对 AfterShip 使用创新技术的肯定。 https://cloud.google.com/customers/aftership/

福利待遇

1、公司提供 Macbook Pro 与 LG 4K 显示器;

2、全额工资购买五险一金,补充购买商业险;

3、带薪病假和年假,转正可享 5 天带薪年假;

4、每人每月 100 元团队聚餐基金(可月累计);

5、购买书籍、在线课程均可报销(不限类别);

6、每天下午茶、每周羽毛球,不定期生日会;

7、每年不定期进行正规医院 /体检机构健康检查;

8、每年不定期市内 /省内 /国内 /国外外出旅游;

9、支持使用可以帮助工作做得更好的付费工具。

我们需要这样的你

我们是一群热爱编程的代码农,但我们不是代码奴!

我们不会单纯接受指令去编程,我们会问为什么要编写这些功能,谁是我们的用户,我们关心用户体验,要打造世界级的产品。

我们为写的代码负责,对代码质素有要求,由代码风格开始,测试,编写技术文档,一丝不苟。 我们注重自动化,使用自动化测试,持续集成与持续交付提升生产力。

我们很挑工具,因为我们深信工欲善其事,必先利其器,选对工具非常重要,善借于物能极大提高开发效率。

我们使用 New Relic 作系统监测、Pingdom, Pagerduty 报警、Cloudflare CDN 加速、Twilio 发 SMS, Sendgrid 发邮件、1Password 管理密码、Zoom 视象会议还有很多很多的工具。

我们为 AfterShip 公司自豪,不是因为公司开明、慷慨,所有工具不论是否要付费,公司愿意给我们支持,全数买单。而是因为 AfterShip 对员工的重视,人才永远放在第一,为员工负责,不断推动我们学习,提升技能。

我们大量使用开源软件,因为我们深信分享是最伟大的。

我们愿意意贡献我们有用的,把好的东西跟全世界分享。

我们使用的 SaaS 工具: https://github.com/AfterShip/SaaS

我们的代码风格: https://github.com/AfterShip/eslint-config-aftership

自动格式化全球电话号码: https://github.com/AfterShip/phone

Koa middleware for New Relic: https://github.com/AfterShip/koa-newrelic

公司地址:深圳市南山区达实智能大厦 40 层(深大 C 口)

AfterShip 期待您的加入!

nuxt 中render:errorMiddleware这个hook的作用是什么?

$
0
0

image.png不太理解官网上的描述,

promise

$
0
0

return new Promise((resolve, reject) => { //…some code });

promise这样用法,发现内存暴涨 ,求大佬解答

CabloyJS全栈开发之旅(1):NodeJS后端编译打包全攻略

$
0
0

背景

毋庸置疑,NodeJS全栈开发包括NodeJS在前端的应用,也包括NodeJS在后端的应用。CabloyJS前端采用Vue+Framework7,采用Webpack进行打包。CabloyJS后端是基于EggJS开发的上层框架。我们知道,EggJS采用的是约定优于配置的原则,当服务启动时,会在约定的目录加载controllerservier诸如此类的文件。那么,我们基于EggJS开发的后端代码,是否也可以像前端一样进行Webpack打包呢?

意义

为什么要提出这样一个命题:NodeJS后端编译打包?

因为NodeJS后端编译打包有如下两个显著的好处:

1. 保护商业代码

编译打包,可以将源码进行丑化,满足保护商业代码的需求。虽然丑化javascript代码无法完全避免反编译,但我们要基于一个原则:丑化最主要的目的是保护开发团队的工作量。可以想象,反编译及以反编译为基础的二次开发,工作量并不小

2. 提升启动性能

编译打包,可以将众多散乱的javascript文件合并成一个文件,从而提升后端服务的启动性能。这在大型项目的开发中,效果更加显著

在接下来的案例中,我们会以模块egg-born-module-test-party为例。该模块后端有63个js源码文件,通过编译打包后只生成一个backend.js文件。当后端服务启动时,一个模块只需加载一个文件,性能肯定优于加载63个文件。如果一个大型项目包含100个业务模块,这种性能优势就会更加明显

目标

进行JS文件打包的工具有很多,由于CabloyJS前端是采用Webpack进行打包,因此,在这里,我们也只探讨Webpack在后端的打包方式

前提条件

我们知道,Webpack是从一个入口文件开始,通过检索require方法,得到一棵完整的文件依赖树,然后把这些依赖树合并成一个文件,最后进行丑化

而EggJS采用的是约定优于配置的原则,文件之间的依赖关系是隐性约定的,而不是通过require显式声明的。因此,在这种机制下面,Webpack打包是不起作用的

但是EggJS的定位就是框架的框架,使得我们可以在EggJS的基础之上开发新的框架。CabloyJS后端就是在EggJS的基础之上,进行了进一步的扩展和封装,使得controllerservicemiddlewareconfig等诸如此类的定义文件,可以通过require方法显式声明,从而可以让Webpack提炼出一棵完整的文件依赖树,进而完成编译打包工作

这篇文章的重点,不是要说明CabloyJS后端是如何对EggJS进行的扩展和封装,而是要说明,在已经实现require显式声明的前提条件下,NodeJS后端如何进行编译打包

准备工作

egg-born-module-test-party是CabloyJS的测试模块,包含大量测试用例。我们以该模块为例来说明NodeJS后端编译打包的方方面面

1. 下载模块

我们先将模块源码下载到本地

$ git clone https://github.com/zhennann/egg-born-module-test-party.git

如果没有git命令行工具,可以直接从GitHub官网下载:https://github.com/zhennann/egg-born-module-test-party

2. 安装依赖

$ npm i 

3. 编译打包

npm run build:backend

核心概念

只要我们指定了入口文件,Webpack就会自动通过require检索文件依赖树。因此,剩下的核心工作,就是通过配置文件来调整Webpack的行为

webpack.base.conf.js

const path = require('path');
const config = require('./config.js');

const nodeModules = {
  require3: 'commonjs2 require3',
};

function resolve(dir) {
  return path.join(__dirname, '../../backend', dir);
}

module.exports = {
  entry: {
    backend: resolve('src/main.js'),
  },
  target: 'node',
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    library: 'backend',
    libraryTarget: 'commonjs2',
  },
  externals: nodeModules,
  resolve: {
    extensions: [ '.js', '.json' ],
  },
  module: {
    rules: [],
  },
  node: {
    console: false,
    global: false,
    process: false,
    __filename: false,
    __dirname: false,
    Buffer: false,
    setImmediate: false,
  },
};

1. entry/output

通过entry/output的组合,我们指定了一个入口文件src/main.js,最终编译打包成一个输出文件backend.js

2. target: ‘node’

Webpack是一个通用的打包工具,既可以用于前端浏览器,也可以用于后端NodeJS。因此,我们需要指定target为node,从而为后端NodeJS打包。比如,在后端node场景下,一些内置的模块就会被排除在打包之列,如fspath等等

3. node

为了让原本为后端NodeJS开发的代码可以在前端浏览器中运行,Webpack提供了模拟策略。比如,globalprocess__filename__dirname都是NodeJS内置的对象。如果代码中包含了这些对象,而代码又需要在前端运行,就需要进行模拟。我们这里讨论的是后端编译,所以,就直接统一赋值false,从而禁用模拟行为

4. resolve.extensions

如果我们在使用require引用源码文件时没有指定文件扩展名,那么Webpack会通过resolve.extensions帮我们匹配合适的文件名

5. module.rules

Webpack除了可以打包js文件,还可以打包css/image/text等资源文件。因为这里是后端打包,所以,不需要设置module.rules

6. externals

在这里重点要说的是节点externals

在实际的业务开发中,我们难免会用到大量第三方模块,这些模块一般都安装在node_modules目录,比如moment。因为我们也是通过const moment=require('moment')的方式引用第三方库,所以,Webpack也会尝试把moment打包进来

一方面,第三方模块数量众多,如果进行打包,最终输出文件过大。另一方面,对于保护商业代码没有任何意义。所以,我们需要想一个办法把这些第三方模块从打包依赖树中排除掉

- 排除moment

如果我们要排除moment,可以这样配置:

externals: {
  moment: 'commonjs2 moment' 
}

- 排除node_modules

如果我们要排除node_modules目录下的所有第三方模块,可以这样配置:

var fs = require('fs');

var nodeModules = {};
fs.readdirSync('node_modules')
  .filter(function(x) {
    return ['.bin'].indexOf(x) === -1;
  })
  .forEach(function(mod) {
    nodeModules[mod] = 'commonjs2 ' + mod;
  });

module.exports = {
  ...
  externals: nodeModules
  ...
}

- 更优雅的策略

针对这种场景,CabloyJS单独开发了一个NPM模块require3https://github.com/zhennann/require3

我们只需要在externals中排除require3这一个模块就可以了。其余的模块都通过require3进行引用,从而轻松避免了被打包的行为

const nodeModules = {
  require3: 'commonjs2 require3',
};

module.exports = {
  ...
  externals: nodeModules
  ...
}

在实际业务代码中,一般这样引用:

const require3 = require('require3');
const moment = require3('moment');

moment通过require3引用,从而避免被Webpack打包

webpack.prod.conf.js

const webpack = require('webpack');
const config = require('./config.js');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');

const env = config.build.env;

const plugins = [
  new webpack.DefinePlugin({
    'process.env': env,
  }),
];

const webpackConfig = merge(baseWebpackConfig, {
  mode: 'production',
  devtool: config.build.productionSourceMap ? 'source-map' : false,
  plugins,
  optimization: {
    runtimeChunk: false,
    splitChunks: false,
    minimize: config.build.uglify,
  },
});

module.exports = webpackConfig;

1. mode: ‘production’

通过指定mode为production,指示Webpack使用与production相关的内置的优化策略

2. devtool

指示Webpack是否生成source map文件,如果要生成,source map的文件格式是什么

详细的格式清单,请参考:https://webpack.js.org/configuration/devtool/

3. optimization.minimize

由于我们只需输出一个单文件,所以只需通过optimization.minimize指示Webpack是否需要最小化(丑化)即可

编译打包

最后,让我们再执行一次NodeJS后端的编译打包指令

npm run build:backend

请教一下async函数这两种写法的区别是什么?

$
0
0

image.png

1 写法 和 2 写法的区别是什么?

xiaos的执行顺序为何不一样?大家一起来看看!!!

cnodejs的登录是怎么设计的?

我在使用Koa和SuperAgent写爬虫脚本时遇到的end()报错

$
0
0

我在使用Koa和SuperAgent写爬虫脚本时遇到了些问题。 但是当我运行项目时,会引发报错。

代码

const Koa = require('koa');
// const request = require('request')
const superagent= require('superagent');

const app = new Koa();


app.use(async ctx => {
  const res = await superagent.get('https://www.google.com');
  ctx.body = res
})


app.listen(3000);

报错信息

Error: end() has already been called, so it's too late to start piping
      at Response.response.pipe (F:\Project\Self_Project\Boxcc\node_modules\superagent\src\node\index.js:923:13)
      at respond (F:\Project\Self_Project\Boxcc\node_modules\koa\lib\application.js:256:43)
      at handleResponse (F:\Project\Self_Project\Boxcc\node_modules\koa\lib\application.js:164:34)
      at process._tickCallback (internal/process/next_tick.js:68:7)

(node:20500) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

  Error: end() has already been called, so it's too late to start piping
      at Response.response.pipe (F:\Project\Self_Project\Boxcc\node_modules\superagent\src\node\index.js:923:13)
      at respond (F:\Project\Self_Project\Boxcc\node_modules\koa\lib\application.js:256:43)
      at handleResponse (F:\Project\Self_Project\Boxcc\node_modules\koa\lib\application.js:164:34)
      at process._tickCallback (internal/process/next_tick.js:68:7)

koa2不同开发者协作时使用不同数据库配置?

$
0
0

在多人协作开发一个koa2的项目的时候,不同开发者用于测试的本地服务器配置可能是不相同的,例如:开发者A本地数据库的密码是123456 B开发者本地数据库的密码是root,如果他们修改的是同一个数据库配置文件的话,代码就会起冲突。

想知道这时候该怎么办,使用.gitignore文件忽略数据库配置文件吗?

js sort中的排序是否受环境影响,比如Android和ios中是否出现顺序不一致.

$
0
0

假如: let arr = [ {nid:3,name:“张三”}, {nid:2,name:“李四”}, {nid:2,name:“王五”} ]; arr.sort((a,b)=>{ return a.nid -b.nid });

运算结果: 是否任何环境下的结果都是: [ {nid:2,name:“李四”}, {nid:2,name:“王五”}, {nid:3,name:“张三”}, ]; 问题? 有没可能出现: [ {nid:2,name:“王五”}, {nid:2,name:“李四”}, {nid:3,name:“张三”}, ];

一起作业网网校直播间招聘Node程序员

$
0
0

1.熟练使用 javascript 异步编程 2.能编写简单算法 3.理解HTTP/TCP协议 4.熟练使用mongodb redis 5.有github开源项目者优先 6.有高并发、分布式处理经验者优先 7.有ELK Kafka rabbitmq protobuf 使用经验者优先 boss直聘小程序链接: qcodeC-f1be3fe402ae792d7579ef47fe7d0bd1.png


sequelize使用sqlite3如何在模型属性定义的setter中获取本条新增数据的自增id?

求大神推荐大前端开发方向的适合笔记本,谢谢

$
0
0

最近在学习nodeJS,再往大前端方向升级自己,但是自己的本是8年的老本已经无法满足自己的开发需求,想更换一台,求大神推荐

嗨,让我带你逐行剖析Vue.js源码

$
0
0

Hello,大家好,我最近在github上做一个关于Vue源码的开源项目,项目内容是: 利用工作之余时间逐行剖析Vuejs源码,将Vuejs源码分为九大模块,逐个击破,希望能帮助到更多的Vue初学者。 1.png阅读地址:https://nlrx-wjc.github.io/Learn-Vue-Source-Code/阅读地址是源码的解析文档,可在线阅读 项目地址:https://github.com/NLRX-WJC/Learn-Vue-Source-Code项目地址里包括了一份带有注释的vue源码和解析文档的源文件 目前数据侦测篇,虚拟DOM篇,模板编译篇,生命周期篇,实例方法篇,全局API篇,过滤器篇均已完成,接下来剖析Vue中的指令和内置组件,后续持续更新中。。。

写作是一件十分枯燥的事情,如果我写的这些文字对你有些许帮助的话,还请赏个star哈~~

另外,本项目受到了阮一峰老师的肯定,已刊登在阮一峰老师微信公众号科技爱好者第87期。 微信图片_20191220152058.png

【1封新邀请】5大主题干货满满 ECUG For Future技术盛宴等你参加!

$
0
0

【1封新邀请】5大主题干货满满 ECUG For Future技术盛宴等你参加!

长图-活动行(12.19)1M.jpg

Q:主办方是否提供发票? A:如需开发票,活动结束后添加工作人员微信(ID:qiniuguanfang),会务组核对无误后,将会在2周内统一安排发放,如遇节假日顺延。

Q:是否有交流群?如何加入? A:成功报名活动后,现场扫码加入现场交流群。

Q:活动是否含餐? A:签到处会统一发放当天午餐券,凭餐券就餐。(就餐处距离活动地点50米)

Q:如何签到? A:活动当天,您需要凭活动行发给您购票的参会二维码,到现场签到处签。如二维码遗失,也可以通过“手机号”签到。

Q:参会人员座位是否有预留?现场是否需要对号入座? A:靠前第一排会给讲师预留座位,观众票座位不对号入座,不预留座位。

egg 插件如何进行单元测试

$
0
0

自己写了一个 egg 的插件,在插件代码 agent.js中 beforeStart 生命周期内添加了插件启动前的一些必要操作,在脚手架生成的单元测试代码中并没有执行,查看插件官方文档也没有对这个情况的单元测试进行说明,请问有了解的大佬吗? 测试代码如下

'use strict';

const mock = require('egg-mock');
const assert = require('assert');

describe('test/apollo-ddz.test.js', () => {
  let app;
  before(() => {
    app = mock.app({
      baseDir: 'apps/apollo-ddz-test',
    });
    return app.ready();
  });

  after(() => app.close());
  afterEach(mock.restore);

  it('should GET /', async () => {
    await app.initApollo();
    assert(app.config.nodeConfig, ' apollo 配置获取失败');
  });
});

Viewing all 14821 articles
Browse latest View live