跳到主要内容

· 阅读需 2 分钟

如何在 Console 中获取当前 redux 的 store 值

如果你安装了 react developer tools ,你可以通过 $r.store.getState(); 来获取,不用改别的代码.

Note: 你需要先打开 react developer tool 之后,让他可用, 不然你回遇到 $r is not defined error


image.png


  1. 开打 developer tools
  2. 点击 「React」 tab
  3. 确认 provider 节点 (or topmost 节点) 现在是被选中的
  4. 然后输入 $r.store.getState(); or $r.store.dispatch({type:"MY_ACTION"}) 到你的浏览器 console

https://stackoverflow.com/questions/34373462/while-debugging-can-i-have-access-to-the-redux-store-from-the-browser-console

· 阅读需 3 分钟

印象

这两个名词可能我们曾经在一些文章中见过或者听说过,但是我们可能不知道它到底代表着什么意思。

只知道可能用户态可以做我们代码中编写的一些逻辑的事情,但是具体涉及到什么系统调用之类的操作就需要在内核态才能完成了。

这可能都只是初步印象。

初识

在 《许式伟的架构课》,我学习到,保护模式下,CPU 引入了“保护环 (Protecting Rings)”的概念,用来对 CPU 指令做权限划分。

如 Intel CPU 通常把权限划分为 Ring 0-3 四个等级。

操作系统内核在 Ring 0 (内核态),常规应用软件在 Ring 3 (用户态)。一次中断调用,不只是 “函数调用”,重要的是改变了执行权限,从用户态到了内核态。

因此,我们上面提到的一些情况,应该是由于我们在用户态时,执行权限较低,而某些需要在内核态才能调用的操作只能交给操作系统内核来完成了。

· 阅读需 3 分钟

较新的 npm 版本可以使用一个新特性来自动给你的 package.json 升级版本号。

为什么需要这个

有很多时候,我们都要去手动改这个版本号,然后再提交一个 commit ,感觉比较麻烦,而且可能有的开发者没有遵循语义化版本 semver 的规则,倒是别人在引用的时候会出现奇奇怪怪的问题。

这个命令怎么用呢

// 升级一个小版本号    1.1.1 -> 1.1.2
npm version patch -m " 升级到 %s ,因为修复了 xxx bug "

// 升级一个中版本号 1.1.1 -> 1.2.0
npm version minor -m " 升级到 %s ,因为添加了 xxxx 特性 "

// 升级一个大版本号 1.1.1 -> 2.0.0
npm version major -m " 升级到 %s ,因为有 xxxx 不兼容的特性 "

会自动修改 package.json 中的版本号,并添加一个 commit 。

· 阅读需 2 分钟

假如git commit 链是

A -> B -> C -> D

如果想把B,C,D都给revert,除了一个一个revert之外,还可以使用range revert

git revert B^..D 

这样就把B,C,D都给revert了,变成:

A-> B ->C -> D -> D'-> C' -> B'

用法

git revert OLDER_COMMIT^..NEWER_COMMIT

如果我们想把这三个revert不自动生成三个新的commit,而是用一个commit完成,可以这样:

git revert -n OLDER_COMMIT^..NEWER_COMMIT
git commit -m "revert OLDER_COMMIT to NEWER_COMMIT"

· 阅读需 2 分钟

https://github.com/axa-group/nlp.js

NLP.js

"NLP.js" is a general natural language utilities for nodejs. Currently supporting:

  • Guess the language of a phrase
  • Fast levenshtein distance of two strings
  • Search the best substring of a string with less levenshtein distance to a given pattern.
  • Get stemmers and tokenizers for several languages.
  • Sentiment Analysis for phrases (with negation support).
  • Named Entity Recognition and management, multilanguage, and accepting similar strings, so the introduced text does not need to be exact.
  • Natural Language Processing Classifier, to classify utterance into intents.
  • Natural Language Generation Manager, so from intents and conditions it can generate an answer.
  • NLP Manager: a tool able to manage several languages, the Named Entities for each language, the utterance and intents for the training of the classifier, and for a given utterance return the entity extraction, the intent classification and the sentiment analysis. Also, it is able to maintain a Natural Language Generation Manager for the answers.

· 阅读需 2 分钟

It is in fact possible to listen to the "expired" type keyevent notification using a subscribed client to the specific channel ( and listening to its message event.

通过 subscribe client 可以监听 __keyevent@{db}__:expired ( db 是你传入的配置 ) 频道来接收过期的事件 ,

const redis = require('redis')
const CONF = {db:3}

let pub, sub

// Activate "notify-keyspace-events" for expired type events
pub = redis.createClient(CONF)
pub.send_command('config', ['set','notify-keyspace-events','Ex'], subscribeExpired)

// Subscribe to the "notify-keyspace-events" channel used for expired type events
function subscribeExpired(e, r){
sub = redis.createClient(CONF)
const expired_subKey = `__keyevent@${CONF.db}__:expired`

sub.subscribe(expired_subKey, function () {
console.log(' [i] Subscribed to "'+expired_subKey+'" event channel : '+r)
sub.on('message', function (chan, msg){
console.log('[expired]', msg)}
)
TestKey()
})
}

//例如,设置一个 key 并设置 10s 超时
function TestKey(){
pub.set('testing', 'redis notify-keyspace-events : expired')
pub.expire('testing', 10)
}

· 阅读需 1 分钟

DB search sql:

  1. 筛选出拥有 openId 的用户,对这些用户进行按年月日分组,并统计每天新增的用户数
db.user.aggregate(
[
{
$match: { "openId": { $exists: true } }
},
{
$group : {
_id : { month: { $month: "$createDate" }, day: { $dayOfMonth: "$createDate" }, year: { $year: "$createDate" } },
count: { $sum: 1 }
}
}
]
)

· 阅读需 1 分钟
// "apn": "^2.1.2",
var apn = require('apn');

var service = new apn.Connection(
"passphrase":"secret",
"pfx":"/path/to/cert.p12",
"production":false
});

var apnVoipProvider = new apn.Provider(voipOptions);

apnNotification = new apn.Notification();
apnNotification.badge = 1;
apnNotification.sound = 'msg.mp3';
apnNotification.alert = 'hello';
apnNotification.payload = {
title: notification.title, id: notificationID, path: notification.path,
};

apnVoipProvider.send(apnNotification, token);

· 阅读需 2 分钟
{
"_id" : "Football",
"ancestors" : [
"Categories",
"Sports and fitness"
],
"parent" : "Sports and fitness"
}

模型定义如下

var mongoose = require('mongoose');

var Category = mongoose.Schema({
_id: String
});

var categorySchema = mongoose.Schema({
ancestors: [Category],
parent: [Category]
});


// Initiate database connection
var db = mongoose.createConnection('mongodb://localhost/Categories');
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
console.log("openDB categories");
});

module.exports.category = db.model('Category', categorySchema);
var categoryModel = require('../models/Category');
var Category = categoryModel.category;

exports.getAncestors = function(req, res) {
if (req.params.id == undefined){res.send("no id specified!"); return;}

Category.findOne({_id: 'Football'}, 'ancestors', function(err, ancestors){
if(err) console.log(err);

res.send(ancestors);
});
}

运行时发生错误

{ message: 'Cast to ObjectId failed for value "Football" at path "_id"',
name: 'CastError',
type: 'ObjectId',
value: 'Football',
path: '_id' }

解决方案

mongoose 默认将 _id 设为 ObjectId 类型。

var categorySchema = mongoose.Schema({
_id: String,
ancestors: [{type: String }],
parent: {type: String}
},{ _id: false });

var Category = mongoose.model( "Category", categorySchema );