Webstorm开发Node.js应用代码自动补全最佳实践

前言

利用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的链接吧,都是照那上面学的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值