|
|
hstarorg / hstardoc Goto Github PK
View Code? Open in Web Editor NEWMy blogs write with markdown.
Home Page: https://www.yuque.com/hstarorg/docs
License: MIT License
My blogs write with markdown.
Home Page: https://www.yuque.com/hstarorg/docs
License: MIT License
function removeDuplicates(nums) {
if (!nums || nums.length === 0) {
return 0;
}
let len = nums.length;
let currentLen = 1;
let current = nums[0];
for (var i = 1; i < len; i++) {
if (nums[i] !== current) {
currentLen += 1;
current = nums[i];
nums[currentLen - 1] = nums[i];
}
}
nums.length = currentLen;
return currentLen;
}
var nums = [1, 1, 2];
console.log(nums, removeDuplicates(nums));
nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4];
console.log(nums, removeDuplicates(nums));
0. mv a/submodule a/submodule_tmp
1. git submodule deinit -f -- a/submodule
2. rm -rf .git/modules/a/submodule
3. git rm -f a/submodule
# Note: a/submodule (no trailing slash,尾巴上没有斜杠)
# or, if you want to leave it in your working tree and have done step 0
3. git rm --cached a/submodule
# 还原目录
mv a/submodule_tmp a/submodule
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
tab_width = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
location / {
root /dist;
try_files $uri $uri/ /index.html; # process history
error_page 404 /index.html; #process history
}
我有一个用来验证技术点和语法使用的项目。要不要考虑下将这个文档项目升级升级?
const fs = require('fs');
const path = require('path');
const http = require('http');
const util = require('util');
const MIME_MAP = {
'.js': 'text/javascript',
'.css': 'text/css',
};
const WEB_ROOT = path.join(__dirname, 'webroot');
const server = http.createServer((req, res) => {
const { url } = req;
let fileUrl = '';
if (/\.[a-zA-Z0-9]+$/.test(url)) {
fileUrl = path.join(WEB_ROOT, url);
} else {
fileUrl = path.join(WEB_ROOT, 'index.html');
}
util
.promisify(fs.exists)(fileUrl)
.then(isExists => {
if (!isExists) {
res.write('404');
return res.end();
}
const extName = path.extname(fileUrl);
const mimeType = MIME_MAP[String(extName).toLowerCase()];
if (mimeType) {
res.writeHead(200, { 'content-type': mimeType });
}
fs.createReadStream(fileUrl).pipe(res);
});
});
server
.listen(80, () => {
const addr = server.address();
console.info('server started...', addr);
})
.on('error', console.error);
题目:请实现如下的函数,可以批量请求数据,所有的URL地址在 urls 参数中,同时可以通过 max 参数控制请求的并发数,当所有的请求结束之后,需要执行 callback 回调函数。发请求的函数可以直接使用 fetch 即可。
function sendRequest(urls: string[], max: number, callback: () => void){
}
通过 jsconfig.json
来实现,核心配置如下:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
},
"target": "ES6",
"module": "commonjs",
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
class Map {
constructor() {
this.$keyObj = {};
this.$valueObj = {};
this.$length = 0;
}
set(key, value) {
const autoKey = `key${Map.idx++}`;
this.$keyObj[autoKey] = key;
this.$valueObj[autoKey] = value;
// 需要判断是否覆盖来控制 $length
}
_getAutoKey(key) {
const keyItem = Object.entries(this.$keyObj).find(x => x[1] === key);
return keyItem[0];
}
get(key) {
const autoKey = this._getAutoKey(key);
if (!autoKey) {
return undefined;
}
return this.$valueObj[autoKey];
}
}
Map.idx = 1;
// Usage
var map = new Map();
var key = new Object();
map.set(key, 1);
console.log(map.get(key), map.get(key) === 1);
import { connect } from 'react-redux';
import { combineReducers, createStore } from 'redux';
const reducerMap = {};
export const reduxHelper = {
store: null, // 缓存全局store
_isFunction(fn) {
return typeof fn === 'function';
},
/**
* 创建Reducer的辅助方法
* @param {object} initialState 默认state
* @param {*} reducerObj
*/
createReducer(initialState, reducerObj) {
return (state = initialState, action) => {
console.log('action', action.type);
const reducerFn = reducerObj[action.type];
if (this._isFunction(reducerFn)) {
return reducerFn.call(null, state, action.payload);
}
return state;
};
},
/**
* 创建页面
* @param {*} pageState
* @param {*} viewComponent
*/
createPage(pageState, viewComponent) {
const self = this;
reducerMap[pageState.namespace] = this.createReducer(pageState.state, pageState.reducers);
function mapStateToProps(state) {
const mapState = {};
// 绑定页面的state属性
Object.keys(pageState.state || {}).forEach(k => (mapState[k] = (state[pageState.namespace] || {})[k]));
// 绑定用户定义的state属性
let newCalcState = {};
if (self._isFunction(pageState.mapStateToProps)) {
newCalcState = pageState.mapStateToProps(state[pageState.namespace], this.store);
}
return { ...mapState, ...newCalcState };
}
function mapDispatchToProps(dispatch) {
const mapDispatch = {};
Object.keys(pageState.actions || {}).forEach(k => {
const actionFn = pageState.actions[k];
if (self._isFunction(actionFn)) {
mapDispatch[k] = () => {
actionFn(dispatch);
};
} else {
console.warn(`key [${k}] not a actions`);
}
});
return mapDispatch;
}
this.store && this.store.replaceReducer(combineReducers(reducerMap));
return connect(mapStateToProps, mapDispatchToProps)(viewComponent);
},
createStore() {
function reducer(state = {}, action) {
return state;
}
this.store = createStore(reducer); // combineReducers(reducerMap)
window.AppState = this.store;
return this.store;
}
};
1、https://github.com/newtriks/generator-react-webpack
Using React with Webpack via Babel
2、https://github.com/kriasoft/react-starter-kit
React.js projects based on React Starter Kit (ES6+, Babel, React.js, Express, Webpack, BrowserSync)
3、https://github.com/stylesuxx/generator-react-webpack-redux
React Webpack Generator including Redux support
4、https://github.com/angular-fullstack/generator-angular-fullstack
Creating MEAN stackapps, using MongoDB, Express, AngularJS, and Node
5、https://github.com/swiip/generator-gulp-angular
AngularJS with Gulp
6、https://github.com/yeoman/generator-angular
AngularJS
7、https://github.com/mcfly-io/generator-mcfly-ng2
Scaffolding an app using angular2 and webpack
8、https://github.com/swirlycheetah/generator-angular2
Angular2 Generator
在根目录新建:.prettierrc.js
,内容如下:
module.exports = {
parser: 'babylon',
printWidth: 120, // 每行最大120字符
semi: true, // 末尾分号
singleQuote: true, // 使用单引号
overrides: [
{
files: ['*.json', '.eslintrc', '.tslintrc', '.prettierrc', '.tern-project'],
options: {
parser: 'json',
tabWidth: 2
}
},
{
files: '*.{css,sass,scss,less,styl}',
options: {
parser: 'css',
tabWidth: 2
}
},
{
files: '*.ts',
options: {
parser: 'typescript'
}
}
]
};
/**
* 快速排序
* @param arr
*/
function quickSort(arr) {
var middle = arr[Math.floor(arr.length / 2)];
var beforeArr = [];
var afterArr = [];
var middleArr = [];
// 分
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i] === middle) {
middleArr.push(arr[i]);
} else if (arr[i] < middle) {
beforeArr.push(arr[i]);
} else {
afterArr.push(arr[i]);
}
}
// 分 End
if (beforeArr.length > 1) {
beforeArr = quickSort(beforeArr);
}
if (afterArr.length > 1) {
afterArr = quickSort(afterArr);
}
return [...beforeArr, ...middleArr, ...afterArr];
}
/**
* 冒泡排序
* @param arr
*/
function bubbleSort(arr) {
const resultArr = arr.slice(0);
for (var i = 0, len = resultArr.length; i < len; i++) {
for (var j = 0; j < len - i - 1; j++) {
if (resultArr[j] > resultArr[j + 1]) {
// 交换
var temp = resultArr[j];
resultArr[j] = resultArr[j + 1];
resultArr[j + 1] = temp;
}
}
}
return resultArr;
}
/**
* 选择排序
* @param arr
*/
function selectSort(arr) {
var resultArr = arr.slice(0);
for (var i = 0, len = resultArr.length; i < len; i++) {
var minIdx = i;
for (var j = i + 1; j < len; j++) {
if (resultArr[j] < resultArr[minIdx]) {
minIdx = j;
}
}
// 交换
var temp = resultArr[i];
resultArr[i] = resultArr[minIdx];
resultArr[minIdx] = temp;
// 装逼写法,实际性能差
// [resultArr[i], resultArr[minIdx]] = [resultArr[minIdx], resultArr[i]];
}
return resultArr;
}
/**
* 插入排序
* @param arr
*/
function insertionSort(arr) {
var resultArr = arr.slice(0);
// 想想打扑克的时候,没摸一张牌,都根据大小插入到手中已有的牌中
for (var i = 1, len = resultArr.length; i < len; i++) {
// 摸牌
var card = resultArr[i];
var j = i - 1;
// 从右往左,看手里的牌,如果比刚摸的牌大,就腾位置
while (j >= 0 && resultArr[j] > card) {
resultArr[j + 1] = resultArr[j];
j--;
}
// 放牌
resultArr[j + 1] = card;
}
return resultArr;
}
/**
* 归并排序
* @param arr
*/
function mergeSort(arr) {
var splitIdx = Math.floor(arr.length / 2);
var beforeArr = arr.slice(0, splitIdx);
var afterArr = arr.slice(splitIdx);
if (beforeArr.length > 1) {
beforeArr = mergeSort(beforeArr);
}
if (afterArr.length > 1) {
afterArr = mergeSort(afterArr);
}
var resultArr = [];
var beforeIdx = 0,
afterIdx = 0;
while (beforeIdx < beforeArr.length || afterIdx < afterArr.length) {
// 前后都有
if (beforeIdx < beforeArr.length && afterIdx < afterArr.length) {
if (beforeArr[beforeIdx] < afterArr[afterIdx]) {
resultArr.push(beforeArr[beforeIdx]);
beforeIdx++;
} else {
resultArr.push(afterArr[afterIdx]);
afterIdx++;
}
} else if (beforeIdx < beforeArr.length) {
// 前还有
resultArr.push(beforeArr[beforeIdx]);
beforeIdx++;
} else {
resultArr.push(afterArr[afterIdx]);
afterIdx++;
}
}
return resultArr;
}
// Prepare
var ARRAY_LENGTH = 10000;
var MAX_VALUE = ARRAY_LENGTH * 10;
var arr = new Array(ARRAY_LENGTH).fill(0).map(x => Math.floor(Math.random() * MAX_VALUE));
console.log('original array', arr);
// Test quick sort
console.time('quick sort');
console.log('after quick sort', quickSort(arr));
console.timeEnd('quick sort');
// Test bulle sort
console.time('bulle sort');
console.log('after bulle sort', bubbleSort(arr));
console.timeEnd('bulle sort');
// Test select sort
console.time('select sort');
console.log('after select sort', bubbleSort(arr));
console.timeEnd('select sort');
// Test insertion sort
console.time('insertion sort');
console.log('after insertion sort', insertionSort(arr));
console.timeEnd('insertion sort');
// Test merge sort
console.time('merge sort');
console.log('after merge sort', mergeSort(arr));
console.timeEnd('merge sort');
原因分析: TouchableWithoutFeedback 需要 <View> 作为直接子集,如果children不是<View />,则不会生效,举例如下:
const Hello = props => <View><Text>Hello</Text></View>;
// Not working
<TouchableWithoutFeedback onPress={()=>alert('working')}>
<Hello />
</TouchableWithoutFeedback>
// Working
<TouchableWithoutFeedback onPress={()=>alert('working')}>
<View>
<Hello />
</View>
</TouchableWithoutFeedback>
原因分析: 由于图像远大于视图,所以在加载该类图片时,容易在低端机型上导致内存不足。解决办法是设置 resizeMethod=resize
(默认为auto)。详情,请参考:https://facebook.github.io/react-native/docs/image.html#resizemethod
// 初版
export const keyboardUtil = {
isIphone() {
return false;
},
init() {
const originalHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.onresize = function resize() {
// 键盘弹起与隐藏都会引起窗口的高度发生变化
const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight < originalHeight) {
alert('展开');
} else {
alert('收起');
}
};
document.body.addEventListener('focusin', () => {
// 软键盘弹出的事件处理
if (this.isIphone()) {
alert('展开');
}
});
document.body.addEventListener('focusout', () => {
// 软键盘收起的事件处理
if (this.isIphone()) {
alert('收起');
}
});
}
};
keyboardUtil.init();
直接返回具体的业务数据,HTTP状态码根据具体的场景列举如下:
{
status: 401, // 和HTTP状态码一致
code: '201452', // 业务定义的错误代码
message: 'Unauthorized', // 错误信息
stack: null // 区分环境,确认是否输出
}
app.use((req, res, next) => {
next({
status: 404,
code: '404',
message: '404 Not Found.'
});
});
app.use((err, req, res, next) => {
let status = 500;
let message = '';
let code = '500';
let stack = null;
// 简单业务错误
if (typeof err === 'string') {
status = 400;
code = '400';
message = err;
} else if (err.isJoi) {// 请求验证错误
status = 400;
code = '400';
message = err.details.map(x => x.message).join('\n');
} else if (err instanceof Error) { // 标准错误处理
if (err.code) {
code = err.code;
}
message = err.message;
stack = err.stack;
} else { // Next({status: 400, code: 'xxx'}) 自定义错误
status = err.status || 400;
code = err.code || '400';
message = err.message;
}
res.status(status).json({
status,
code,
message,
stack
});
});
apt-get update -qq > /dev/null
# 安装依赖库
apt-get update && apt-get install -y --no-install-recommends apt-utils > /dev/null
apt-get install -qq --no-install-recommends \
build-essential \
autoconf \
curl \
git \
lib32stdc++6 \
lib32z1 \
lib32z1-dev \
lib32ncurses5 \
libc6-dev \
libgmp-dev \
libmpc-dev \
libmpfr-dev \
libxslt-dev \
libxml2-dev \
m4 \
ncurses-dev \
ocaml \
openjdk-8-jdk \
openssh-client \
pkg-config \
python-software-properties \
ruby-full \
software-properties-common \
unzip \
wget \
zip \
zlib1g-dev > /dev/null
# 安装Node
curl -sL -k https://deb.nodesource.com/setup_${NODE_VERSION} \
| bash - > /dev/null && \
apt-get install -qq nodejs > /dev/null
apt-get clean > /dev/null && \
rm -rf /var/lib/apt/lists/ && \
npm install --quiet -g npm > /dev/null && \
npm install --quiet -g react-native-cli > /dev/null && \
npm cache clean --force > /dev/null
echo "installing fastlane" && \
gem install fastlane --quiet --no-document > /dev/null
# Get the latest version from https://developer.android.com/studio/index.html
ENV ANDROID_SDK_TOOLS_VERSION="3859397"
# Get the latest version from https://developer.android.com/ndk/downloads/index.html
ENV ANDROID_NDK_VERSION="15c"
ENV ANDROID_HOME="/opt/android-sdk" \
ANDROID_NDK="/opt/android-ndk" \
JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
# 安装sdk Tools
echo "installing sdk tools" && \
wget --quiet --output-document=sdk-tools.zip \
"https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS_VERSION}.zip" && \
mkdir --parents "$ANDROID_HOME" && \
unzip -q sdk-tools.zip -d "$ANDROID_HOME" && \
rm --force sdk-tools.zip
# 安装ndk
echo "installing ndk" && \
wget --quiet --output-document=android-ndk.zip \
"http://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_VERSION}-linux-x86_64.zip" && \
mkdir --parents "$ANDROID_NDK_HOME" && \
unzip -q android-ndk.zip -d "$ANDROID_NDK" && \
rm --force android-ndk.zip && \
# Install SDKs
# Please keep these in descending order!
# The `yes` is for accepting all non-standard tool licenses.
mkdir --parents "$HOME/.android/" && \
echo '### User Sources for Android SDK Manager' > \
"$HOME/.android/repositories.cfg" && \
yes | "$ANDROID_HOME"/tools/bin/sdkmanager --licenses > /dev/null && \
echo "installing platforms" && \
yes | "$ANDROID_HOME"/tools/bin/sdkmanager \
"platforms;android-26" \
"platforms;android-25" \
"platforms;android-24" \
"platforms;android-23" \
echo "installing platform tools " && \
yes | "$ANDROID_HOME"/tools/bin/sdkmanager \
"platform-tools"
echo "installing build tools " && \
yes | "$ANDROID_HOME"/tools/bin/sdkmanager \
"build-tools;26.0.2" "build-tools;26.0.1" "build-tools;26.0.0" \
"build-tools;25.0.3" "build-tools;25.0.2" \
"build-tools;25.0.1" "build-tools;25.0.0" \
"build-tools;24.0.3" "build-tools;24.0.2" \
"build-tools;24.0.1" "build-tools;24.0.0" \
"build-tools;23.0.3" "build-tools;23.0.2" "build-tools;23.0.1"
echo "installing extras " && \
yes | "$ANDROID_HOME"/tools/bin/sdkmanager \
"extras;android;m2repository" \
"extras;google;m2repository"
echo "installing play services " && \
yes | "$ANDROID_HOME"/tools/bin/sdkmanager \
"extras;google;google_play_services" \
"extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2" \
"extras;m2repository;com;android;support;constraint;constraint-layout;1.0.1"
echo "installing Google APIs" && \
yes | "$ANDROID_HOME"/tools/bin/sdkmanager \
"add-ons;addon-google_apis-google-24" \
"add-ons;addon-google_apis-google-23" \
"add-ons;addon-google_apis-google-22" \
"add-ons;addon-google_apis-google-21"
# 安装Git
apt-get install git
https://github.com/mingchen/docker-android-build-box/blob/master/Dockerfile
放在
http {
}
中,
gzip on;
gzip_min_length 1k;
gzip_buffers 16 64k;
gzip_http_version 1.1;
gzip_comp_level 4;
gzip_types text/plain application/javascript text/css application/xml;
gzip_vary on;
var SSH = require('simple-ssh');
var argv = require('yargs').argv;
var ssh = new SSH({
host: '11.11.11.11',
user: 'root',
pass: 'xxx',
baseDir: '/opt/docker-builds/'
});
var opt = {
out: function (stdout) {
console.log(stdout);
},
err: function (stderr) {
console.error(stderr);
}
};
var out = function (stdout) {
console.log(stdout);
}
const name = argv.name || argv.n;
const version = argv.version || argv.v;
if(!name || !version){
return console.error('must provide --name(-n) and --version(-v)');
}
const projectFolder = name;
const projectName = `jay/${name}`;
const versionNo = version;
ssh.exec(`docker build -t ${projectName}:${versionNo} ${projectFolder}`, opt)
//.exec(`docker push xxx.com/${projectName}:${versionNo}`, opt) // 没有仓库需要注销
.start();
1、http://slides.com/tangguichuan/es6-in-modern-development
ES6 in modern
2、https://camsong.github.io/redux-in-chinese/index.html
Redux中文文档
3、Angular2入门项目:https://angularclass.github.io/angular2-webpack-starter/,先学会使用,再改造。
4、Angular2入门项目:https://github.com/mgechev/angular2-seed
5、http://www.primefaces.org/primeng/ Angular2组件
class MysqlClient {
constructor(pool) {
this.pool = pool;
}
/**
* Begin database transaction
*/
beginTransaction() {
return this._getConnection()
.then(conn => {
return new Promise((resolve, reject) => {
conn.beginTransaction(err => {
if (err) { return reject(err); }
conn.inTransaction = true;
resolve(conn);
})
});
});
}
/**
* Commit transaction
* @param {any} conn
*/
commitTransaction(conn) {
return new Promise((resolve, reject) => {
conn.commit(err => {
if (err) {
conn.rollback(() => {
this._releaseConnection(conn, true);
reject(err);
});
} else {
this._releaseConnection(conn, true);
resolve();
}
});
});
}
/**
* Rollback transaction
* @param {any} conn
*/
rollbackTransaction(conn) {
return new Promise((resolve, reject) => {
conn.rollback(() => {
this._releaseConnection(conn, true);
resolve();
});
});
}
/**
* Get a database connection
*/
getConnection() {
return this._getConnection();
}
/**
* Execute sql, return query result(array)
* @param {string} sqlString
* @param {object | array} values
* @param {any} conn
*/
executeQuery(sqlString, values, conn = null) {
return this._execute(sqlString, values, conn);
}
/**
* Execute sql, return single result(the first one)
* @param {string} sqlString
* @param {object | array} values
* @param {any} conn
*/
executeScalar(sqlString, values, conn = null) {
return this._execute(sqlString, values, conn)
.then(results => {
if (results.length === 0) {
return null;
}
return results[0];
});
}
/**
* Execute sql, return affected rows
* @param {string} sqlString
* @param {object | array} values
* @param {any} conn
*/
executeNonQuery(sqlString, values, conn = null) {
return this._execute(sqlString, values, conn)
.then(results => {
return results.affectedRows;
});
}
/**
* Execute sql, return insertId(for auto id)
* @param {string} sqlString
* @param {object | array} values
* @param {any} conn
*/
executeInsert(sqlString, values, conn = null) {
return this._execute(sqlString, values, conn)
.then(results => {
return results.insertId;
});
}
/**
* private function, get db connection
*/
_getConnection() {
return new Promise((resolve, reject) => {
this.pool.getConnection((err, conn) => {
if (err) { return reject(err); }
resolve(conn);
});
});
}
/**
* Release connection
* @param {any} conn
* @param {boolean} closeTran
*/
_releaseConnection(conn, closeTran = false) {
if (closeTran) {
conn.inTransaction = false;
}
conn.release();
}
/**
* Execute sql, return resuluts;
* @param {string} sqlString
* @param {object|array} values
* @param {any} conn
*/
_execute(sqlString, values, conn) {
let { sql, params } = this._processSqlAndParameter(sqlString, values);
let p = conn ? Promise.resolve(conn) : this._getConnection();
return p.then(conn => {
return new Promise((resolve, reject) => {
conn.query(sql, params, (err, results, fields) => {
// If conn is in transaction, not release
if (!conn.inTransaction) {
this._releaseConnection(conn);
}
if (err) { return reject(err); }
resolve(results);
});
});
});
}
_processSqlAndParameter(sqlString, params) {
let result;
// If is an array, direct return.
if (Array.isArray(params)) {
result = {
sql: sqlString,
params: params.slice()
};
} else {
// Replace object to array, and use ? replace @Property
let paramArr = [];
if (params) {
let paramKeys = Object.keys(params);
sqlString = sqlString.replace(/@[a-zA-Z0-9]+/g, (match, offset, str) => {
let matchKey = match.replace('@', '');
if (paramKeys.indexOf(matchKey) >= 0) {
paramArr.push(params[matchKey]);
return '?';
}
return match;
});
}
result = {
sql: sqlString,
params: paramArr
};
}
return result;
}
}
module.exports = MysqlClient;
V1 版本:
import { EventEmitter } from "events";
const bus = new EventEmitter();
// 缓存队列
const cacheMap: Map<
string,
{
status: "pending" | "loading" | "succeed" | "failed";
data?: any;
queue: string[];
}
> = new Map();
async function asyncCache(cacheKey: string, asyncFn: () => Promise<any>) {
// 先初始化缓存
if (!cacheMap.has(cacheKey)) {
cacheMap.set(cacheKey, { status: "pending", queue: [] });
}
const fnId = Math.random().toString(16).slice(2);
// 缓存对象,可直接修改对象属性
let cacheItem = cacheMap.get(cacheKey);
// 有缓存成功的数据,直接返回
if (cacheItem.status === "succeed") {
return cacheItem.data!;
}
// 加入队列
cacheItem.queue.unshift(fnId);
// 有请求中的数据,先加入队列
if (cacheItem.status === "loading") {
await new Promise((resolve) => {
bus.on("ASYNC_DONE", () => {
// 如果数据缓存成功或者队列中轮到自己,就停止等待
if (
cacheItem.status === "succeed" ||
fnId === cacheItem.queue[cacheItem.queue.length - 1]
) {
resolve(1);
}
});
});
}
cacheItem = cacheMap.get(cacheKey);
// 有缓存成功的数据,直接返回
if (cacheItem.status === "succeed") {
return cacheItem.data!;
}
cacheItem.status = "loading";
return Promise.resolve()
.then(() => {
return asyncFn();
})
.then((data) => {
// 记录缓存状态和缓存数据
cacheItem.status = "succeed";
cacheItem.data = data;
return data;
})
.catch((reason) => {
cacheItem.status = "failed";
return Promise.reject(reason);
})
.finally(() => {
// 结束了自己出队
cacheItem.queue.pop();
// 通知其他等待的请求
bus.emit("ASYNC_DONE");
});
}
class SQLiteClient {
constructor(db) {
this.db = db;
}
beginTransaction() {
return this._exec('BEGIN TRANSACTION;');
}
commitTransaction() {
return this._exec('COMMIT TRANSACTION;');
}
rollbackTransaction() {
return this._exec('ROLLBACK TRANSACTION;');
}
executeQuery(sql, params) {
return this._execute('all', sql, params);
}
executeNonQuery(sql, params) {
return this._execute('run', sql, params)
.then(result => {
return result.changes;
});
}
executeScalar(sql, params) {
return this._execute('get', sql, params);
}
executeInsert(sql, params) {
return this._execute('run', sql, params)
.then(result => {
return result.lastID;
});
}
_execute(type, sql, params) {
if (!sql) {
throw new Error('SQL not found.');
}
return new Promise((resolve, reject) => {
// Process dynamic sql param
sql = sql.replace(/#[a-zA-Z0-9]+/g, (match, offset, source) => {
return params[match.slice(1)] || '';
});
// Not allow surplus parameters, Need get the used parameter keys
let sqlNeedParamKeys = (sql.match(/@[a-zA-Z0-9]+/g) || []).map(x => x.slice(1));
params = params || {};
let sqlParams = {};
// Process parameters
sqlNeedParamKeys.forEach(k => {
sqlParams[`@${k}`] = params[k];
});
this.db[type](sql, sqlParams, function (err, row) {
if (err) { return reject(err) }
if (type === 'run') {
row = {
lastID: this.lastID,
changes: this.changes
};
}
resolve(row);
});
});
}
// Execute sql
_exec(sql) {
return new Promise((resolve, reject) => {
this.db.exec(sql, (err, row) => {
if (err) { return reject(err) }
resolve();
});
});
}
}
module.exports = SQLiteClient;
"importSort": {
".js, .jsx, .es6, .es,": {
"parser": "babylon",
"style": "module-compact"
},
".ts, .tsx": {
"parser": "typescript",
"style": "eslint",
"options": {}
}
},
配置到package.json中。
function lengthOfLongestSubstring(text) {
function hasRepeatChar(str) {
var strArr = str.split('');
var obj = {};
strArr.forEach(x => (obj[x] = true));
return strArr.length != Object.keys(obj).length;
}
var longStr = '';
var len = text.length;
var tempStr = '';
for (var i = 0; i < len - longStr.length; i++) {
tempStr = text[i];
for (var j = i + 1; j < len; j++) {
if (hasRepeatChar(tempStr + text[j])) {
if (longStr.length < tempStr.length) {
longStr = tempStr;
}
break;
} else {
tempStr += text[j];
}
}
if (!hasRepeatChar(tempStr)) {
if (longStr.length < tempStr.length) {
longStr = tempStr;
}
}
}
// console.log(longStr);
return longStr.length;
}
var len;
len = lengthOfLongestSubstring('abcdefghijklmn');
console.log(len, len === 14);
len = lengthOfLongestSubstring('cbca');
console.log(len, len === 3);
len = lengthOfLongestSubstring('c');
console.log(len, len === 1);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.