[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]

Prince追悼ダンスを踊りました

Princeが好きだったのですが、この前亡くなってしまいました。

Prnceにありがとうの気持ちを表現するべくPrince追悼ダンスを踊りました。



DynamoDBでテーブルに入っているデータをすべて取得する

Node.jsからDynamoDBでテーブルに入っている全てのデータを取得しようとするとscan()メソッドを使うのですが、デフォルトの挙動では 最大1MBまでのデータしか読み込むことができません。
すべてのデータを取得する場合は、scanした時に読み込めていないデータが有る場合はLastEvaluatedKeyが返ってきますのでこれを使って再帰的にscanする必要があります。

...
var db = new AWS.DynamoDB({apiVersion: '2012-08-10'});
readAll(callback) {
  var objects = [];
  var params = {
    TableName: ‘tablename’
  };
  doScan(params,(err,res) => {
    return callback(err,res);
  });
}

doScan(params,callback)  {
    
  
  db.scan(params,(err,res) => {

    //最後の内容まで取得できなかった場合はdoScanを繰り返す
    if (res['LastEvaluatedKey']){
      console.log('found last evaluatedKey');
      params.ExclusiveStartKey = res.LastEvaluatedKey;
      
      res.Items.map((item) => {
        objects.push(item);
      })
      this.doScan(params,callback);
    }else {
      //全てのデータが読み込めたらcallbackを返す
      console.log('finished scan’);
      res.Items.map((item) => {
        objects.push(item);
      })
      return callback(err, objects);
    }
  });
}