coを使って非同期処理を綺麗に書く

coを使うとJavaScriptの非同期処理を同期的に書くことができてかなり読みやすいコードが書けるようになります。

例えば、非同期にファイルの中身を取得するプログラムでもかなりすっきりとした感じになります。

'use strict';
let co = require('co');
let fs = require('fs');

let readFile = (path) => {
	return new Promise((resolve,reject) => {
		fs.readFile(path,(err,data) => {
			if (err) return reject(err);
			let jsonData = JSON.parse(data);
			return resolve(jsonData);
		})
	})
};


co(function *(){
	//success
	let read = readFile('./data.json');
	let data = yield read;
	//dataにdata.jsonの中身が入っている
	console.log(data)

}).catch((err) => {
	//error
	console.log(err);

});

node-scheduleで指定した時刻にタスクを実行する

Node.jsで指定した時刻にタスクを実行させるにはnode-scheduleというライブラリが便利です。 時刻の指定はCron方式、Date形式で指定できるのが気に入っていてとても柔軟に扱えます。

使い方

5分ごとにタスクを実行

 let schedule = require('node-schedule');

 let j = schedule.scheduleJob(' */5 * * * *', function(){
  //Do something

 });

3時間後にタスクを実行

  let schedule = require('node-schedule');

 //fireDate: タスクを実行する時刻
  let fireDate = new Date();
  fireDate.setSeconds(fireDate.getSeconds() + 60 * 60 * 3);


  schedule.scheduleJob(fireDate, () => {
   //Do something
  });

[Swift] Background状態で通信を行う

Background状態とは

アプリを使用している状態はForegroundといいます。アプリを終了すると、アプリはSuspendedになります。
Suspendedではコードを実行することはできませんが、このSuspendedになる前にコードを実行できるのがBackground状態です。

iOS7から用意されたNSURLSessionを使うことでBackground状態で通信処理が行うことができます。 NSURLSessionを使ったプロセスはアプリとは異なるプロセスへ移され、アプリの状態に関係なく通信処理を行います。
なので、アプリが終了されたとしても一連の通信処理を完了させることができます。

Example

func backgroundRequest(){
  let bgID = “backgroundID”
  let configuration:NSURLSessionConfiguration =      NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(bgID)

  let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
  let urlStr = “…”
  let params: [String: AnyObject] = [
                        "user_id":"foo"
                    ]
  let url:NSURL = NSURL(string:urlStr)!
  let request = NSMutableURLRequest(URL: url)  request.HTTPMethod = “POST”
  request.addValue("application/json", forHTTPHeaderField:"Content-Type")


  do {
      try   request.HTTPBody = “POST”
      NSJSONSerialization.dataWithJSONObject(params,               
      options: NSJSONWritingOptions.PrettyPrinted)
      let task = session.downloadTaskWithRequest(request)
      task.resume()
 }catch{
 }
}

func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
	//failed
        session.finishTasksAndInvalidate()
}
    
func URLSessionDidFinishEventsForBackgroundURLSession(session: NSURLSession) {
	//success
        session.finishTasksAndInvalidate()
}

[ES6] 複数のPromise文をつなげて書く

let isValid = (age) =>{
  return new Promise((resolve,reject) => {
    if (age < 20) return reject('err:未成年は決済できません');
    return resolve();
  });
};

let startPayment = () => {
  console.log('決済中です...');
  return new Promise((resolve,reject) => {
    setTimeout(() => {
      let n = Math.floor(Math.random() * 100);
      if (n % 2 === 0){
        return resolve('決済が完了しました');
      }else{
        return reject('err:決済できませんでした');
      }
    },2000);
  });
};

1つ目のPromise、2つ目のPromiseのいずれかでエラーが発生すると、catch…が呼ばれる。それ以降then…でチェーンしたメソッドは呼ばれない。

未成年の場合


 isValid(10).then(() => {

 }).then(() => {
   return startPayment()
 }).then((msg)=> {
  console.log(msg);
 }).catch((err) => {
   console.log(err);
 });

//err: 未成年は決済できません

大人の場合

isValid(30).then(() => {

 }).then(() => {
   return startPayment()
 }).then((msg)=> {
   console.log(msg);
 }).catch((err) => {
   console.log(err);
 });
//決済が完了しました OR err:決済できませんでした

ちなみに上のコードはPromise.allを使って以下のように書くことが出来る。

Promise.all([isValid(30),startPayment()]).then((vals) => {
console.log(vals)
}).catch((err) => {
console.log(err)
}

Promiseを使うことでcallbackがネストするよりははるかに読みやすく書ける。

lodashで良く使う2つのテクニック

最近はlodashを良く使うようになったので自分の備忘録としていい機会なので今後のためにまとめておく。

ショートカット記法

ショートカット記法を覚えたらfilterやfind,map等で配列を操作するコードがかなりシンプルになって生産性が高まった。

_.find(collection,dict)

配列の中からage.S === 300 となるオブジェクトを取得する。undefinedチェックをしなくていいので便利。

_.find([{age: {S:300}},{age:{}},{age: undefined}],{age: {S:300}})
// {age: {S: 300}}

_.map(collection,key)

配列の中に入っているオブジェクトのage.Sを全て返す。

_.map([{age: {S:300}},{age:{S:33}}],'age.S')
// [300,33]

メソッドチェーン

メソッドチェーンを実現するにはtapとchainがあるけど、 chainは配列の中身のデータを加工することができないが、tapだと配列の中身のデータを加工することが出来るという違いがある。

_.chain

var users = [
  { 'user': 'barney',  'age': 36 },
  { 'user': 'fred',    'age': 40 },
  { 'user': 'pebbles', 'age': 1 }
];

var youngest = _
  .chain(users)
  .sortBy('age')
  .map(function(o) {
    return o.user + ' is ' + o.age;
  })
.head()
.value() // value()で返り値を取得
// → 'pebbles is 1'

_.tap

_([1, 2, 3])
 .tap(function(array) {
   // Mutate input array.
   array.pop();
 })
 .reverse()
 .value();
// → [2, 1]