前言
利用Webstorm开发Node.js应用,最烦恼的就是代码自动补全问题了。由于JavaScript的弱类型特性,Webstorm等IDE在智能代码补全功能上心有余而力不足,由Java、C++等转过来的程序员会很不适应。这里介绍Webstorm支持的代码自动补全功能,能够一定程度缓解问题。
首先,看Webstorm的官方文档:
https://www.jetbrains.com/help/webstorm/2016.3/creating-jsdoc-comments.html
里面讲了Webstorm支持大部分的Google Closure Compiler的注解,并且能够根据这些注解进行智能代码补全。
这是Google Closure Compiler支持的注解,基本上是jsdoc规范的子集
https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compile
这是Google Closure Compiler类型及类型表达式规范
https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System
这里列举一个代表的代码段几个常用的:
1自定义对象结构
/* *******************************************
* Copyright (c) 2016-2017
* XXXXXXXX Co.,Ltd. All rights reserved.
* Project : Task
* File : UserDao.js
* Created : 2017-02-08
* Author : liangjiang
* *******************************************/
const crypto = require('crypto');
const mongodb = require('./mongodb/mongodb');
const User = require('../entity/User');
const RandomUtil = require('../util/RandomUtil');
const CODE = require('../../const/code');
const logger = require('pomelo-logger').getLogger('debug-level', __filename, process.pid);
const Collection = require('mongodb').Collection;
/**
* Class to operate user.
*/
class UserDao {
/** @typedef {{username:string, password:string}} UserData */
/**
* Create a new account.
*
* @param {UserData} opt
* @return {Promise<?User>}
*/
static createNewAccount(opt) {
return new Promise(function (resolve, reject) {
let user;
/** @type {Collection} */
let tempCollection;
mongodb.collection('users')
.then((/** Collection */collection) => {
tempCollection = collection;
return collection.findOne({username: opt.username});
})
.then((doc) => {
if (doc == null) {
let userData = {
username: opt.username || '',
password: UserDao._saltAndHash(opt.password || '')
};
user = new User(userData);
return tempCollection.insertOne(user.toObject(), {safe: true});
} else {
resolve(null);
}
})
.then((result) => {
user.setId(result.insertedId);
resolve(user);
})
.catch((err) => {
logger.error(err);
reject(err);
});
});
}
/**
* Auto login.
*
* @param {UserData} opt
* @return {Promise<?User>}
*/
static autoLogin(opt) {
return new Promise(function (resolve, reject) {
mongodb.collection('users')
.then((/** Collection */collection) => {
return collection.findOne({username: opt.username});
})
.then((doc) => {
if (doc == null) {
resolve(null);
}
if (doc.password == opt.password) {
resolve(new User(doc));
}
resolve(null);
})
.catch(function (err) {
logger.error(err);
reject(err);
});
});
}
/**
* Manual login.
*
* @param {UserData} opt
* @return {Promise<User|number>}
*/
static manualLogin(opt) {
return new Promise(function (resolve, reject) {
mongodb.collection('users')
.then((/** Collection */collection) => {
return collection.findOne({username: opt.username});
})
.then((doc) => {
if (doc == null) {
resolve(CODE.AUTH.LOGIN.FA_USER_NOT_EXIST);
}
if (UserDao._validatePassword(opt.password, doc.password)) {
resolve(new User(doc));
} else {
resolve(CODE.AUTH.LOGIN.FA_PASSWORD_INVALID);
}
})
.catch((err) => {
logger.error(err);
reject(err);
});
});
};
/**
* Validate password.
*
* @private
* @param {string} plainPass - Plain password.
* @param {string} hashedPass - Hashed password.
* @return {boolean} If equal.
*/
static _validatePassword(plainPass, hashedPass) {
let salt = hashedPass.substr(0, 10);
let validHash = salt + UserDao._md5(plainPass + salt);
return hashedPass === validHash;
}
/**
* Salt and hash.
*
* @private
* @param {string} pass - Password to hash.
* @return {string} Hashed password.
*/
static _saltAndHash(pass) {
let salt = UserDao._generateSalt();
return salt + UserDao._md5(pass + salt);
};
/**
* Generate a salt.
*
* @private
* @return {string} Random string of 10 characters.
*/
static _generateSalt() {
return RandomUtil.randomString(10);
};
/**
* Calculate md5 value of a string.
*
* @private
* @param {string} str - String to md5.
* @return {string} Md5 value.
*/
static _md5(str) {
return crypto.createHash('md5').update(str).digest('hex');
};
}
module.exports = UserDao;
利用@typedef注解可以定义对象结构,如下:
/** @typedef {{username:string, password:string}} UserData */
函数开头的@private告诉Webstorm该方法是私有,Webstorm不会再外部调用时进行提示。
@param和@return可以定义函数的参数类型和返回值类型。
/**
* Validate password.
*
* @private
* @param {string} plainPass - Plain password.
* @param {string} hashedPass - Hashed password.
* @return {boolean} If equal.
*/
如果是Promise类型,最好加上模板类型,既resolve(result)的中result的类型,这样使用await时就不会提示有问题。
/**
* Deal with the command: downloadList.
*
* @param {object} req
* @return {Promise<Answer>}
*/
async function doDownloadList(req) {
let /** Array<Download> */ downloads = await DownloadDao.getDownloads({targetId: req.session.target._id, status: 'unfinished'});
let data = [];
for (let download of downloads) {
data.push({id: download._id, saveName: download.filename});
}
return {answer: 'ok', data: data};
}
更详细的用法还是看上面那两个关于Google Closure Compiler的链接吧,都是照那上面学的。