顯示具有 nodejs 標籤的文章。 顯示所有文章
顯示具有 nodejs 標籤的文章。 顯示所有文章

2017年12月14日 星期四

Startup pm2 command for Windows Server 2012 R2


需在 windows server 重新啟動的時候,
自動執行 pm2 start someapp.js,
pm2 有 startup command 提供此機制,但不支援 windows,
以下是 worked solution


The following is my latest solution which works really well:
  • create a specific Windows user for running node scripts
  • login as that user and npm install pm2 -g
  • pm2 start all the apps I would like to have startup
  • pm2 save to save the current process list
  • create a .bat file and within it paste the following commands:
@echo off
set HOMEDRIVE=C:
set HOMEPATH=\Users\%USERNAME%
set path=C:\Users\%USERNAME%\AppData\Roaming\npm;%path%
pm2 delete all & pm2 resurrect

Use Windows Task Scheduler to create a task that:
  • runs "whether user is logged on or not"
  • is Triggered "At startup"
  • is configured to run the .bat file that we created


2017年10月16日 星期一

query pagination data with mongoose


目前透過 mongoose 查詢 pagination 資料覺得很麻煩,
先取得 total count 再取 page data,
目前使用的方式如下:

    user
        .find(where)
        .count()
        .then((totalCount) => {
            if (totalCount && totalCount > 0) {
                return user.find(where)
                    .select('field1 field2 field3 filed4')
                    .sort({ createdOn: -1 })
                    .skip(skip)
                    .limit(limit)
                    .exec()
                    .then((rows) => {
                        return {
                          rows:rows
                          totalCount: totalCount
                    });
            } else {
                 return res.status(200)
                        .json({
                         rows: [],
                         skip: skip,
                         limit: limit,
                         totalCount: 0
                        })
                        .end();
            }
        })
        .then((result) => {
                 return res.status(200)
                        .json({
                         rows: result.rows,
                         skip: skip,
                         limit: limit,
                         totalCount: result.totalCount
                        })
                        .end();
        })
        .catch((err) => {
            next(err);
        });

寫得落落長,太麻煩了,花了一些時間查查,有沒有什麼方便的方式
原來 mongoose 有 pagination plugin 可以用,真的是佛心來的,
使用方式如下:

Installation:
npm install mongoose-paginate

Usage:
var mongoose         = require('mongoose');
var mongoosePaginate = require('mongoose-paginate');
 
var schema = new mongoose.Schema({ /* schema definition */ });
schema.plugin(mongoosePaginate);
 
var Model = mongoose.model('Model',  schema); // Model.paginate() 

Model.paginate([query], [options], [callback])

所以上面的範例可以改成:
var where   = {};
var options = {
    select:   'field1 field2 field3 filed4',
    sort:     { createdOn: -1 },
    lean:     true,
    offset:   20, 
    limit:    10
};
user.paginate(where, options).then(function(result) {
    return res.status(200)
                        .json({
                         rows: result.docs,
                         skip: skip,
                         limit: limit,
                         totalCount: result.total
                        })
                        .end()
});

太好了,是不是簡單很多!

reference:https://www.npmjs.com/package/mongoose-paginate

Avoiding Callback Hell in Node.js - Promise


寫 nodejs 就會用到非同步的 callback
就會碰到所謂的「callback hell」的囧境
什麼是 callback hell? 如下所示:

doSomeAsyncFunc(function () {
  doSomeAsyncFunc(function () {
    doSomeAsyncFunc(function () {
      doSomeAsyncFunc(function () {
        doSomeAsyncFunc(function () {
          doSomeAsyncFunc(function () {
            doSomeAsyncFunc(function () {
              doSomeAsyncFunc(function () {
                doSomeAsyncFunc(function () {
                  // 我到底在第幾層地獄啊!?
              })
            })
          })
        })
      })
    })
  })
})



這樣光要看懂就很辛苦了,還要怎麼維護程式碼呢?

有幾種解決方式:

  1. async.waterfall
  2. promise
  3. async/await

上一篇介紹了 async.waterfall,現在來看看 Promise 如何使用

1. 先將 doSomeAsyncFunc 包裝成 promise 物件
doSomeAsyncFunc(function () {
  return new Promise(function(resolve, reject) {
    // do something, possibly async
    if (/* everythings fine */) {
      resolve(result);
    } else {
      reject(err);
    }
  });
}

2. 使用 primise.then 即可攤平 callback hell

var promise = doSomeAsyncFunc();
promise.then((result) => {
  // get result
  return '2';
}).then((result2) => {
  // get result2 ('2')
  return '3';
}).then((result3) => {
  // get result3 ('3')
}).catch((err) => {
  // error handling
});

3. 所以一開始的範例就可以改成:

var promise = doSomeAsyncFunc();
promise.then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).then((result) => {
  // do something
  return doSomeAsyncFunc();
}).catch((err) => {
  // error handling
});

這樣就可以攤平可怕的 callback hell,回到地球表面囉!

2017年9月26日 星期二

Avoiding Callback Hell in Node.js - async.waterfall


寫 nodejs 就會用到非同步的 callback
就會碰到所謂的「callback hell」的囧境
什麼是 callback hell? 如下所示:

doSomeAsyncFunc(function () {
  doSomeAsyncFunc(function () {
    doSomeAsyncFunc(function () {
      doSomeAsyncFunc(function () {
        doSomeAsyncFunc(function () {
          doSomeAsyncFunc(function () {
            doSomeAsyncFunc(function () {
              doSomeAsyncFunc(function () {
                doSomeAsyncFunc(function () {
                  // 我到底在第幾層地獄啊!?
              })
            })
          })
        })
      })
    })
  })
})


這樣光要看懂就很辛苦了,還要怎麼維護程式碼呢?

有幾種解決方式:

  1. async.waterfall
  2. promise
  3. async/await


先來看看 async.waterfall 如何解決問題

步驟如下:

1. 先安裝 async package :   $ npm install --save async

2. import async package :   var async = require("async");

3. waterfall(tasks, callback) 的說明:

Runs the tasks array of functions in series, each passing their results to the next in the array. However, if any of the tasks pass an error to their own callback, the next function is not executed, and the main callback is immediately called with the error.

簡單來說,只要 error 的參數是 null ,就會一直往下丟 callback,
若中途呼叫 callback 且 error 參數不為 null ,則直接進入 mail callback

範例:
async.waterfall([
    function(callback) {
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback) {
        // arg1 now equals 'one' and arg2 now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback) {
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'
});

也就是說,一開始的 callback hell sample 可以改成:
async.waterfall([
    function(callback) {
        doSomeAsyncFunc1(function (error, result) {
            callback(error, result);
        });
    },
    function(callback) {
        doSomeAsyncFunc2(function (error, result) {
            callback(error, result);
        });
    },
    function(callback) {
        doSomeAsyncFunc3(function (error, result) {
            callback(error, result);
        });
    }
    ......
], function (err, result) {
    // main callback 
    if (err) {
        // do something
    } else if {
        // do something
    }
});

這樣就可以攤平可怕的 callback hell,回到地球表面囉!

reference: https://caolan.github.io/async/docs.html#waterfall

2017年1月26日 星期四

visual studio code debug for nodejs + express + consign


撰寫 nodejs 在 visual studio code 進行 debug,
可以參考∶ Node.js Applications with VS Code
簡單來說會在專案根目錄新增 .vscode 資料夾,再新增 launch.js 檔
並在 configurations/program 指定起啟程式,即可進行斷點除錯,如下圖

環境說明∶
  • 關於 express server 端的程式碼皆放在「根目錄/api/」下
  • 起啟的 js 檔放在「根目錄/api/index_debug.js」
  • 其中使用 consign 指定載入順序,讓網站可正常執行,
    如∶ config file -> db -> authority -> routing -> ....... -> start server 
問題∶
在 api 資料夾直接下 command : $node index_debug.js 可正常執行,
但是直接在 visual studio code 執行 debug 卻什麼事情也沒發生,斷點也沒有反應,

































solution:
查了一下 consign 文件,verbose 設為 false 會關掉 log,導致發生什麼事都不知道,
verbose 設為 true 後,即可發現是因為路徑問題導致


只要指定好起啟目錄即可,將 cwd 設為 api 就解決囉! 如下圖



這樣就可以開心使用 visual studio code debug 功能囉!
終於讓開發能更有效率,不然班加不完啊!