分类 软件 下的文章

官方教程

Quick Start

按官方的Quick Start理解如下:
安装

npm install @feathersjs/feathers --save

服务端

创建一个类来管理一种资源,并且其同步async方法与REST的各种操作相对应,如messages资源。这个类称之为Service服务。

操作CRUD REST HTTP feathers class async 函数 完成事件
增 create POST async create(data, params) // 其中data为通过POST发送来的JSON,并且已经JSON.parse成了对象。params可选,下同 created
删 delete DELETE remove(id, params) removed
替换改 update PUT update(id, data, params) updated
合并改 update PATCH patch(id, data, params) patched
查所有 read GET messages async find(params) //返回值为GET的返回值,为JS对象。JSON化(JSON.stringify)由feathers完成,不需要我们操作 -
查部分 read GET mesages?xx=x&xxx=xx async get(id, params) {} -

另外有个查header的REST HEAD 似乎没有对应,这个命令和GET类似,只是不返回内容只返回header

class MessageService {
  //初始化时候需要创建一个存储资源的地方,示例中先在内存中建立了一个数组,后面估计可以改为数据库的访问
  constructor() { 
    this.messages = [];
  }

  async find () {
    // Just return all our messages
    return this.messages;
  }

  async create (data) {
    // The new message is the data merged with a unique identifier
    // using the messages length since it changes whenever we add one
    const message = {
      id: this.messages.length,
      text: data.text
    }

    // Add new message to the list
    this.messages.push(message); 

    return message;
  }
app.use('/messages', new MessageService());  // 这儿注册资源的url地址和资源的class服务

完整代码:

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');

// A messages service that allows to create new
// and return all existing messages
class MessageService {
  constructor() {
    this.messages = [];
  }

  async find () {
    // Just return all our messages
    return this.messages;
  }

  async create (data) {
    // The new message is the data merged with a unique identifier
    // using the messages length since it changes whenever we add one
    const message = {
      id: this.messages.length,
      text: data.text
    }

    // Add new message to the list
    this.messages.push(message);

    return message;
  }
}

// Creates an ExpressJS compatible Feathers application 创建一个Express兼容的Feathers APP
const app = express(feathers());  

// Parse HTTP JSON bodies. 
// 从这儿开始注册中间件,先是自动对JSON数据解析的,也就是请求时header写着 ‘content-type: application/json’  的
app.use(express.json());
// Parse URL-encoded params 
// 解析 URL-encoded 格式的请求体数据,也就是请求时header写着‘content-type: application/x-www-form-urlencoded’ 的
app.use(express.urlencoded({ extended: true }));
// Host static files from the current folder
// 这个替代了nginx作用了,对.html .css等静态文件做http服务
app.use(express.static(__dirname));
// Add REST API support 
app.configure(express.rest());
// Configure Socket.io real-time APIs
app.configure(socketio());
// Register an in-memory messages service, 
// 这个是一句抵6句的REST注册了,否则要app.get/app.post/app.delete一个一个去搞定REST接口
app.use('/messages', new MessageService());
// Register a nicer error handler than the default Express one
app.use(express.errorHandler());

// Add any new real-time connection to the `everybody` channel 
// 一个连接connection类似一个会话session,一个频道channel类似MQTT的一个topic,
// 这儿在一个连接产生时将这个连接加入到everybody的频道中
app.on('connection', connection =>
  app.channel('everybody').join(connection)
);
// Publish all events to the `everybody` channel
// 一个事件events类似于MQTT的一个消息,当然这个events也是node的标准events,data是消息内容,
// publish的操作类似于MQTT的pub。sub操作是通过监听事件 .on 来做的,具体来说可以是监听created事件。
app.publish(data => app.channel('everybody'));

// Start the server
app.listen(3030).on('listening', () =>
  console.log('Feathers server listening on localhost:3030')
);

// For good measure let's create a message
// So our API doesn't look so empty 先自行加一条数据到messages资源中
app.service('messages').create({ 
  text: 'Hello world from the server'
});

客户端

直接访问http://localhost:3030/messages就相当于GET操作REST API
再创建一个index.html作为客户端来访问

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Feathers Example</title>
  <link rel="stylesheet" href="//unpkg.com/feathers-chat@4.0.0/public/base.css">
  <link rel="stylesheet" href="//unpkg.com/feathers-chat@4.0.0/public/chat.css">
</head>
<body>
  <main id="main" class="container">
    <h1>Welcome to Feathers</h1>
    <form class="form" onsubmit="sendMessage(event.preventDefault())">
      <input type="text" id="message-text" placeholder="Enter message here">
      <button type="submit" class="button button-primary">Send message</button>
    </form>

    <h2>Here are the current messages:</h2>
  </main>

  <script src="//unpkg.com/@feathersjs/client@^4.3.0/dist/feathers.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
  <script type="text/javascript">
    // Set up socket.io 实时连接监听地址
    const socket = io('http://localhost:3030');
    // Initialize a Feathers app
    const app = feathers();

    // Register socket.io to talk to our server
    app.configure(feathers.socketio(socket));

    // Form submission handler that sends a new message
    async function sendMessage () {
      const messageInput = document.getElementById('message-text');

      // Create a new message with the input field value, 通过REST POST发送消息,当然这一切都隐藏了
      await app.service('messages').create({
        text: messageInput.value
      });

      messageInput.value = '';
    }

    // Renders a single message on the page,增加一条新的message
    function addMessage (message) {
      document.getElementById('main').innerHTML += `<p>${message.text}</p>`;
    }

    const main = async () => {
      // Find all existing messages
      const messages = await app.service('messages').find();

      // Add existing messages to the list
      messages.forEach(addMessage);

      // Add any newly created message to the list in real-time
      app.service('messages').on('created', addMessage);
    };

    main();
  </script>
</body>
</html>

除了REST以外的概念

如果只是实现REST就不想要下面这些了

实时通讯

类似MQTT咯。REST只能根据客户端的请求相应,而实时通讯可以根据事件主动向客户端推送消息
Channels 实时通讯通道,类似于MQTT的topic吧
Events 事件系统

使用cli构建

安装cli: npm install @feathersjs/cli -g
使用cli

mkdir feathers-chat
cd feathers-chat/
feathers generate app

交互式命令行输出:

D:\r\feathers_proj\feather-chat>feathers generate app
? Do you want to use JavaScript or TypeScript? JavaScript
? Project name feather-chat
? Description
? What folder should the source files live in? src
? Which package manager are you using (has to be installed globally)? npm
? What type of API are you making? REST, Realtime via Socket.io
? Which testing framework do you prefer? Mocha + assert
? This app uses authentication Yes
? Which coding style do you want to use? ESLint
? What authentication strategies do you want to use? (See API docs for all 180+ supported oAuth providers) Username + Pa
ssword (Local)
? What is the name of the user (entity) service? users
? What kind of service is it? NeDB
? What is the database connection string? nedb://../data
   create package.json
   create config\default.json
   create public\favicon.ico
   create public\index.html
   create .editorconfig
   create src\app.hooks.js
   create src\channels.js
   create src\index.js
   create src\logger.js
   create src\middleware\index.js
   create src\services\index.js
   create .gitignore
   create README.md
   create src\app.js
   create test\app.test.js
   create .eslintrc.json
   create config\production.json
   create config\test.json
   create src\services\users\users.service.js
   create src\authentication.js
   create test\authentication.test.js
   create src\services\users\users.class.js
   create src\models\users.model.js
   create src\services\users\users.hooks.js
   create test\services\users.test.js
.....

目录简述

  • config/ 配置
  • public/ html静态文件,大概意思是nginx都不用装了
  • src/ 源码。包括hooks钩子和services服务。services里默认有一个users服务。
  • middleware/ 放express的中间件
  • models/ 放数据库模型,也就是和数据库的链接映射。里面默认有一个users.model.js提供与users表的映射
  • test/ 测试

根目录文件简述

  • app.js feathers应用的配置
  • app.hooks.js app的钩子
  • authentication.js 认证系统
  • channels.js 频道系统,用于实时通讯
  • index.js 入口

运行命令

# 启动
npm start
# 测试
npm test
# 开发模式,代码更新自动重运行
npm run dev

通过cli创建services

feathers generate service

通过cli交互创建需要的文件

λ feathers generate service                                                                                                                                         
? What kind of service is it? NeDB                                                                                                                                  
? What is the name of the service? messages                                                                                                                         
? Which path should the service be registered on? /messages                                                                                                         
? Does the service require authentication? Yes                                                                                                                      
   create src\services\messages\messages.service.js                                                                                                                 
    force src\services\index.js                                                                                                                                     
   create src\services\messages\messages.class.js                                                                                                                   
   create src\models\messages.model.js                                                                                                                              
   create src\services\messages\messages.hooks.js                                                                                                                   
   create test\services\messages.test.js                                                                                                                            
npm WARN ws@7.4.6 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself.                                          
npm WARN ws@7.4.6 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself.                                      
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules\fsevents):                                                                             
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})   

up to date in 8.347s                                                                                                                                                
npm WARN ws@7.4.6 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself.                                          
npm WARN ws@7.4.6 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself.                                      
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules\fsevents):                                                                             
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})   

up to date in 4.056s                                                                                                                                                

基本是创建了src/services目录下的三个文件,挂载到index.js上,并创建连接数据库的对应model.js和测试文件

Hooks钩子

钩子可以在服务的前、后、错误时运行。钩子与服务是多对多的关系,相当于对多个不同服务中类似的功能提取公因数。

const createdAt = async context => {
  context.data.createdAt = new Date();

  return context;
};

app.service('messages').hooks({
  before: {
    create: [ createdAt ]
  }
});

Cli方式创建钩子

命令是:

feathers generate hook                                                          

交互示意:

λ feathers generate hook                                                          
? What is the name of the hook? process-message                                   
? What kind of hook should it be? before                                          
? What service(s) should this hook be for (select none to add it yourself)?       
 messages                                                                         
? What methods should the hook be for (select none to add it yourself)? create    
   create src\hooks\process-message.js                                            
    force src\services\messages\messages.hooks.js                                 

之前公司研究了看板以后,最早使用leangoo,基于看板管理迭代和需求池。在看板方面算是比较强大的了。
同时开发的人管理bug使用的是easybug,简单易用,倒也足够。
后来,还是开发的同事介绍,说腾讯新搞了个tapd,试用了一下,集合看板、需求管理、bug管理、文档管理为一体,一次性替代了leangoo/easybug/石墨的功能,我再加一个画原型的墨刀就搞定一切了。tapd另外还有我没怎么用的迭代(我用看板替代)、故事墙(还是看板替代)、Wiki功能。不过从tapd的开发思想上来说,似乎看板的优先级要低于迭代和故事墙,因为看板的功能还是比不上leangoo的看板,燃尽图这些反而是在迭代功能里的。
另外,个人任务管理用的是wunderlist,主要是够简单。

其他我没怎么用过的,看起来又还不错的工具包括:
redmine,老牌管理工具了。
禅道,国产中被提及最多的工具之一。
JIRA, tapd中有JIRA导入功能,看来有很多借鉴。商业版,要收费
Tower,团队协作工具,有阿里钉钉支持,当然老沈和老张嘛。
teambition, 跟tower差不多,或者说tower跟他差不多?也是团队协作工具

  • 接近于用看板管理各项事务。主操作界面“任务”也是看板式的。
  • “分享”功能其实是共享文档,不过无法发布excel或者md,只能是常规富文本。
  • 支持敏捷,不过是高级功能。包括需求、缺陷、迭代(看起来像看板)、统计功能,需要付费开通。普通的“敏捷开发”模板,核心还是只是一个名叫“任务”的看板而已。
    ClearQuest, IBM的,商业版要付费。
    Bugzilla, mozilla基金会的产品,产品比较老,看起来界面也比较原始,大概能看作是easybug的复杂版?当然mozilla基金会的东西自然是开源免费的了。
    Trac,开源免费,看上去体验比bugzilla稍好些,有wiki、roadmap、timeline、源码管理(这个……还是用git吧...)、任务管理等功能。不过应该还是属于哪个IE的时代的...
    gitlab,能不能说git出品必属精品?至少从界面上来看要现代一些。使用上,和Github看起来很像,同样有代码仓库的管理,issues事务的管理,只是issues除了以列表的方式查看,还可以用看板的方式查看,也能定义标签。不过其思想上貌似是“一切皆issue”,提出的每一个内容,标签上可以归于交互、前端、平台、API甚至是bug、功能等等,但都一切平等都是issue,最后issue都要变为代码合并到版本中去,并且变为closed状态。有点儿大道至简的感觉。另外就是包括CI/CD过程(持续集成、持续交付),自动安排任务进行打包测试、上线。
    另外gitlab还有个snippets功能,有点儿像是论坛,但都是以代码讨论为中心的。不知道有没有自动发布的内容。
    另外,从网上文章来看,github和gitlab最大区别似乎是,后者可以创建免费私人仓库,有一些权限方面的管理。其他都差不多。

这篇文章讲得清楚,也说了怎么解决。总之是mysql的utf-8编码的问题。

不过文章里指定了工具为phpAdmin,我这儿用的阿里万网,是DMS,额,好像是阿里自己开发的工具,没有那个“数据库操作-整理-选择 utf8mb4_unicode_ci”的地方。好在还有其他参考:

How can I convert entire MySQL database character-set to UTF-8 and collation to UTF-8?
How to easily convert utf8 tables to utf8mb4 in MySQL 5.5

发现有命令行转数据库和表的方式,如下:

ALTER DATABASE databasename CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

准备工作是看一下Php和mysql支持不,php要求版本大于等于5.5,mysql也是要求大于等于5.5.3

哦,看来我这个是不行了。我的mysql居然才5.1.48... 看来还是断了这个念想吧...

mysql>select version();
+---------------------+
| version()           |
+---------------------+
| 5.1.48-log          |
+---------------------+
共返回 1 行记录,花费 34 ms.

还是介绍一下。

  • 先转数据库,每一家名字不一样,自己填database name
    ALTER DATABASE databasename CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 再转表

alter table typecho_comments convert to character set utf8mb4 collate utf8mb4_unicode_ci;
alter table typecho_contents convert to character set utf8mb4 collate utf8mb4_unicode_ci;
alter table typecho_fields convert to character set utf8mb4 collate utf8mb4_unicode_ci;
alter table typecho_metas convert to character set utf8mb4 collate utf8mb4_unicode_ci;
alter table typecho_options convert to character set utf8mb4 collate utf8mb4_unicode_ci;
alter table typecho_relationships convert to character set utf8mb4 collate utf8mb4_unicode_ci;
alter table typecho_users convert to character set utf8mb4 collate utf8mb4_unicode_ci;

* 最后通过ftp改网站根目录数据库配置文件`config.inc.php`
```php
$db->addServer(array (
  'host'      =>  localhost,
  'user'      =>  'youruser',
  'password'  =>  'yourpassword',
  'charset'   =>  'utf8mb4', //修改这一行
  'port'      =>  3306,
  'database'  =>  'yourdatabase'
), Typecho_Db::READ | Typecho_Db::WRITE);

参考:
JS转换HTML转义符
Decode & back to & in JavaScript

还是stackoverflow上的回答比较专业

var encodedStr = 'hello &amp; world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

借此写个函数

function decoder(str){
    var parser = new DOMParser;
    var dom = parser.parseFromString(
        '<!doctype html><body>' + str,
        'text/html');
    var decodedString = dom.body.textContent;
    return decodedString;
}

短距离无线协议选择,这儿有一篇小米的生态链总监孙鹏在2015年7月的文章WiFi、ZigBee、BLE用哪个?小米内部是这样选的,可作为参考。简而言之,如下:

插电的设备,用WiFi;
需要和手机交互的,用BLE;
传感器用ZigBee。
原因是什么呢?因为WIFI一旦配置好了最方便,BLE低功耗可用于电池供电的设备,传感器用Zigbee是因为那时候BLE还没有传感器的互通标准。
那么,WIFI和BLE其实是面向不同的应用,那么BLE和Zigbee重叠度就有点儿高了。在百度百科里看到Zigbee的介绍,最早作为经典蓝牙的补充,弥补其缺点的,然而后来蓝牙联盟又收了BLE,Zigbee的发展感觉有点儿难讲。
另外一篇比较BLE和Zigbee以及很少听过的ANT+的文章:BLE的最大竞争对手是ZigBee、Wi-Fi、Ant+以及一系列广泛的专有协议,转载于2016年1月,里面写到ANT+,提到一句话:
ANT+在BLE问世之前的确很成功,但在BLE问世之后,大多数此类厂商拥有了了另一个低功耗通信协议。由于BLE得到了更多主设备的支持,它被证明是一个更加保险的选择。因此,Fitbit、Jawbone、Tom-tom等主流可穿戴设备厂商都选择了BLE。
长江后浪推前浪,前浪死在沙滩上。
那么Zigbee呢,文中说Zigbee支持的终端数量更大,还支持Mesh网络,这个BLE不支持。
从这篇文章:蓝牙会干掉Zigbee吗?的观点来看,在消费者领域,蓝牙很可能会干掉Zigbee了,而在工业领域,由于其冗余性、大规模的特点,可能Zigbee仍有用武之地。
如果WiFi和蓝牙将在家庭市场一统江湖,分别垄断固定和移动连接,那么乐鑫的ESP32看来是大有前途咯!

Chrome浏览器下载提示恶意文件,或者来自于不受谷歌信任的网站,即使你将此文件下载完,也会提示“chrome已经将其拦截”,给你的按钮只有“放弃”。点击放弃以后,可是哪儿都找不到……其实我下载的就是一个.zip,里面是人畜无害的.pdf文件,怎么找回呢?
再次重新下载,可以使用“另存为”存到桌面,这时候桌面将生成一个临时文件,名字是xxxxx.crdownload,等待下载完毕,弹出让你“放弃”的按钮,千万别放弃,把这个.crdownload文件复制一份,或者改个名,加上它本来的后缀,如.zip,你就成功保全了它。

所有都好用, 自然是用库

推荐的库是iconv, iconv-lite.
不过就是临时转一下, 还需要建一个npm项目不成? 有简单的办法吗?下面讲.

先说一个node.js和chrome兼容的做法: charCodeAt

'中文'.charCodeAt(0).toString(16) // "4e2d"
'中文'.charCodeAt(1).toString(16) // "6587"
'abc'..charCodeAt(0).toString(16) // "61"

这种方法得一个一个去取, 当然有个for循环会更方便
这个方法的逆方法是String.fromCharCode(new Uint16Array([0x6587])) ,打印出
这儿奇怪的是上述内容都是双字节编码...

chrome和firefox等浏览器实现了一个TextEncoder的类

只是这个类现在只支持utf8编码, 不再支持其他类型,如gbk.

var x = new TextEncoder().encode('中文')
//输出 Uint8Array(6) [228, 184, 173, 230, 150, 135]
(new Array(...x)).map(v=>v.toString(16)).join()
//"e4,b8,ad,e6,96,87"  上面先转普通数组, TypedArray不能用map将数字转为字符串, 然后再转16进制表示的字符串,再连接

逆类是TextDecoder, 这个支持gbk

new TextDecoder().decode(new Uint8Array([228, 184, 173, 230, 150, 135]))
//输出 "中文"
new TextDecoder('gbk').decode(new Uint8Array([0xd6,0xd0, 0xce, 0xc4]))
//输出 "中文"
(new TextDecoder('gbk')).decode(new Uint16Array([0xd6d0, 0xcec4]))
// "兄奈", 字节序问题, 这儿应该是小端字节序, 将字节反过来就对了
(new TextDecoder('gbk')).decode(new Uint16Array([0xd0d6, 0xc4ce]))
// "中文"

既然JVM上面可以运行客体语言, 那么会不会有人在JVM上运行JavaScript? 还别说, 真有!

ringo.js

先说第一个项目,ringo,它在github上有600多的star数目.
解压缩放入path后运行ringo, 进入其REPL, 我试了一下, 下面的是可以运行的:

f = function(s){console.log(s)}
f('hello')

ringo有自己的包管理工具rp, 跟npm差不多. 不过需要安装:

ringo-admin install grob/rp

然而我在windows 10上安装却会报错:

Wrapped java.lang.UnsupportedOperationException
        at fs.js:1100 (changePermissions)
        at C:\l\tools\admin\install.js:86 (installPackage)
        at C:\l\tools\admin\install.js:156 (main)
        at C:\l\tools\admin\main.js:14 (main)
        at C:\l\tools\admin\main.js:30

哦...这就无法继续了...
一个语言的强大在于其库的强大,如果它能同时使用npm和java库,那就真的非常强大了,看来暂时是无法验证了.

java8 jjs: oracle nashorn

没错. Java8支持JavaScript, 这个运行工具就是jjs, 正式名字叫做Nashorn. Oracle官方的这篇文章 Oracle Nashorn: A Next-Generation JavaScript Engine for the JVM有一些说明, 我查了一下我的java, 还真是8:

λ java -version                                                         
java version "1.8.0_111"                                                
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)                   
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)        

根据文章说, jjs和java在同一目录, 能运行java就意味着jjs也能运行, 先看看版本:

λ jjs -v                  
nashorn 1.8.0_111         
jjs>                      

果然进来了呢! 试了一下, 居然不支持console.log...
对应的打印命令,居然是print...
对此, 文章是这样解释的: 虽然我们兼容ECMA, 但是浏览器环境下的特有变量我们是不支持的,比如window, console这些.

好处呢? 一个是在Java中调用JavaScript代码,还能用到JavaScript的库, 恩,这个感觉比较符合oracle的思路...
文中举例了在Java中调用mustache.js库的方式.

package sample2;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.FileReader;

public class Mustache {

  public static void main(String... args) throws Throwable {
    ScriptEngineManager engineManager = 
new ScriptEngineManager();
    ScriptEngine engine = 
engineManager.getEngineByName("nashorn");
    engine.eval(new FileReader("src/sample2/mustache.js"));
    Invocable invocable = (Invocable) engine;

    String template = "Email addresses of {{contact.name}}:\n" +
        "{{#contact.emails}}\n" +
        "- {{.}}\n" +
        "{{/contact.emails}}";

    String contactJson = "{" +
        "\"contact\": {" +
        "\"name\": \"Mr A\", \"emails\": [" +
        "\"contact@some.tld\", \"sales@some.tld\"" +
        "]}}";
Object json = engine.eval("JSON");
    Object data = 
invocable.invokeMethod(json, "parse", contactJson);

    Object mustache = engine.eval("Mustache");
    System.out.println(invocable.invokeMethod(
mustache, "render", template, data));
  }
} 

另一个是在JavaScript中调用Java,这个我比较关心. 哦, 直接调用就好了, 很简单的样子:

print(java.lang.System.currentTimeMillis());

Java对象也可以使用new来实体化, 这个就酷了:

var file = 
new java.io.File("sample.js");
print(file.getAbsolutePath());
print(file.absolutePath); 

java.io.File虽然没有定义absolutePath,但是定义了getAbsolutePath(), jjs会自动增加absolutePath这个属性. 对set也是一样.
这样来看,nashorn很可能可以同时使用部分npm库和java库,看上去很强大的样子.
剩下一个问题就是速度了. nashorn和v8对比速度如何? 从这篇文章来说,还是要差一些的. 对ES的支持呢? 似乎是支持到ES5.1,还没有对新特性的支持. 试了一下ES6中的箭头函数, 果然是没有支持的. 这点上就远不如node.js那么积极啦.

jjs> var a = ()=>{print()}                                                    
ECMAScript Exception: SyntaxError: <shell>:1:9 Expected an operand but found )
var a = ()=>{print()}                                                         
         ^                                                                    

nashorn项目官网

rhino.js

哦, 这个就是被java8抛弃的那个, mozilla基金会的项目, 官网, github项目地址

显示CPU使用情况

其实很简单.在"开发者选项"中,倒数第7项左右,有个"显示CPU使用情况",打开即可.
显示信息的解释(转载自知乎):
三个数字代表在三个不同间隔下(1, 5, 15分钟)估算的平均负载(load average)
数字下面显示的就是正在运行的各种进程,包括系统和应用程序的执行序(process)。
一般都是看后面的两个数字,了解系统是否会有长时间处在高负载的状况下,
短暂、突发的高负载并不会造成问题,可忽略不管。
数字越小越好,数字较大就表示机器过载或有某种问题。
单核CPU ,全负载是1.0 ,超过1.0 就表示有执行序在排队等待。
双核CPU ,全负载是2.0 ,因为它可以同时运行两串执行序。
如想要进一步了解,可用Android Show CPU Usage 找看看。
三星、华为等机子显示的数字也许代表不同的用途和意义?
或许就跟一些app 显示CPU, memory, I/O的负载一样。
顺便提一下,数字行和各个执行序都会有蓝、绿、红色的底色条,
数字行的底色条是所有执行序的底色条的总和。

  • 蓝色呈现的是低优先度的执行序
  • 绿色呈现的是一般优先度的执行序
  • 红色呈现的是系统内核的执行序

android studio

另外,还可以使用android studio 3的Android Profiler来查看.位置在View->Tool Windows->Android Profiler中. 前提是要连接USB线.

Flyme OS的性能监视器

FlymeOS在开发者选项的最后一项是性能优化,其中有个性能监视器,可以对CPU进行监控

其他Tips

在拨号菜单输入*#*#4636#*#* 可以看到一些神秘内容:)

Java作为当年为解决C/C++问题出现的语言, 在当今快速开发的环境下,总觉得已经慢慢不合时宜.而JVM经过多年的优化,已经早已摆脱当年速度太慢的恶名.于是多种新的语言使用不同于Java的新的语法运行于JVM之上,提供更加现代化的语言特性.
知乎上有这个问答: Groovy,Clojure和Kotlin都是基于jvm的语言,那他们在实际项目中的运用场景有什么区别?
为什么很多语言选择在JVM上实现?
我觉得JVM仍然越来越流行的重要原因,是跨平台和速度.

  • 跨平台尤其重要. Javascript, Python如此流行的最重要原因可能也是如此. Java能超越C/C++, 我认为它是第一个提出跨平台概念,一次编码多处运行理念的语言,这其中,JVM功不可没.
  • 速度是另一个重要原因. node.js作为晚于python的后起之秀, 之所以比python有更多的实际应用, 是因为其在并发速度上面甚至超过了很多传统语言.
  • 丰富的库也是很必要的. Java多年积累,库是极其丰富的,JVM天生拥有这些库, 这一点常常是从头做起的新生语言难以做到的.
    另外, JVM上可以任一实现的客体语言(Guest),可以紧跟时代趋势,包含新的语言特性. 比如现在流行的动态化,脚本化,函数式编程等,这样,语言常新,而JVM将用不过时.

ANDROID studio 3.0.1版本默认新建项目下build.gradle如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'


        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

增加了代理,又增加了aliyun的镜像后, 还是无法下载对应的包, 不知道是不是3.0.1太新了, 修改为2.3.3:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {

    repositories {
    // maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
       // google()
       jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'


        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        // maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
       // google()
       jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

下载成功!又提示我gradle太旧,我的是3.1,它说至少得3.3以上. 它也不提示个升级方法...
升级gradle: 下载,解压,改路径到bin.

测试金字塔,TestPyramid,主要是说你应该运行更多的单元测试,因为它又便宜有全面, 并且所有你在上层GUI测试中遇到的问题, 都应该通过增加和修改单元测试来得到完全地覆盖.

对比Appium和Espressoappium-vs-espresso. Appium是GUI黑盒, Espresso也是GUI测试, 不过要有源码, 可以说是白盒.
溢栈网上对appium和Espresso的对比.appium-vs-espresso-for-automated-testing-framework.主要是说espresso有如下优点:

  • 可以直接测试Activity
  • 可以直接测试Toast
  • 可以看到测试覆盖率

robolectric也是白盒, 但据他所说, 他更接近于黑盒, 并且有如下优势:

  • 不需要启动模拟器,直接在JVM中运行,速度快
  • 模拟绝大多数真实设备行为
  • 不需要mockito这样的mock框架

谷歌官方的android APP测试指导