孤独プログラマー譚

孤独死が近い。

Promise 非同期メソッドの結果で処理を分岐

よくあるのが、オブジェクトをresolveし、その中に分岐用のフラグを含める。
まったく美しくない。見ててつらい。

const confess = (iLoveMai) => {
  console.log(iLoveMai ?
    '私は白石麻衣を愛しています。'
    : '私は白石麻衣を愛していません。'
  )
}

const { love: iLoveMai1 } = await Promise.resolve({ love: true })
confess(iLoveMai1) // 私は白石麻衣を愛しています。
const { love: iLoveMai2 } = await Promise.resolve({ love: false })
confess(iLoveMai2) // 私は白石麻衣を愛していません。


resolve, reject で分岐させる。
オブジェクトにフラグを持たせる必要がない。
シンプルで分かりやすい。良い!

const iLoveMai3 = await Promise.resolve().then(() => true)
confess(iLoveMai3) // 私は白石麻衣を愛しています。
const iLoveMai4 = await Promise.reject().catch(() => false)
confess(iLoveMai4) // 私は白石麻衣を愛していません。

Promise catch()からthen()への復帰

catch()からthen()へ。
そして、then()からcatch()へ。

const promise = Promise.resolve()

promise
.then(() => {
  console.log(1)
  throw new Error()
})
.catch(() => {
  console.log(2)
  return
})
.then(() => {
  console.log(3)
  throw new Error()
})
.catch(() => {
  console.log(4)
  return
}) // 1 2 3 4


以下のようにも、書き換えられる。

promise
.then(() => {
  console.log(1)
  return Promise.reject(new Error())
})
.catch(() => {
  console.log(2)
  return Promise.resolve()
})
.then(() => {
  console.log(3)
  return Promise.reject(new Error())
})
.catch(() => {
  console.log(4)
  return Promise.resolve()
}) // 1 2 3 4

Promise reject と catch

以下の2つは、書き換えられる。

const foo = () => {
  return new Promise((resolve, reject) => reject(new Error('foo_value')))
}

const bar = async () => {
  throw new Error('bar_value')
}


catchで受ける。

foo().catch((err) => console.log(err.message)) // foo_value
bar().catch((err) => console.log(err.message)) // bar_value


resolve = async + return
reject = async + throw
という解釈でいいと思う。

JavaScript Promise.thenメソッドの返却値

asyncメソッドと似たような考え方でいいと思う。

const promise = new Promise(resolve => resolve())

const foo = promise.then(async () => {
  await new Promise(resolve => {
    setTimeout(resolve, 1000)
  })
  return 'foo_value'
})

const bar = promise.then(() => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('bar_value')
    }, 2000)
  })
})

foo.then((res) => console.log(res)) // 1秒後にfoo_value
bar.then((res) => console.log(res)) // 2秒後にbar_value

Promiseオブジェクトをreturnすると、そのままそのPromiseオブジェクトがthen()の返却値となる。
Promiseオブジェクト以外をreturnすると、Promiseでラッピングされて返却される。

JavaScript Promiseとasyncの書き換え

以下の2つ、Promiseとasyncメソッドは書き換えられる。

foo() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('foo_value')
    }, 1000)
  })
}
async bar() {
  await new Promise((resolve) => {
      setTimeout(resolve, 1000)
  })
  return 'bar_value'
}


メソッドから返却されたPromiseオブジェクトはawaitできる。
asyncメソッドの返却値もPromiseオブジェクトとなる。

const val1 = await this.foo()
console.log(val1) // foo_value
const val2 = await this.bar()
console.log(val2) // bar_value


awaitでなく、then()メソッドでも対応できる。
asyncメソッドの返却値(Promiseオブジェクト)からthen()メソッドを使用することもできる。

const promise1 = this.foo()
promise1.then(val => console.log(val)) // foo_value
const promise2 = this.bar()
promise2.then(val => console.log(val)) // bar_value

Angular ルーティング

ルーティングの最低限の構成。

/* app-routing.module.ts */

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { FooComponent } from './foo/foo.component';

const routes: Routes = [
  { path: 'foo', component: FooComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

router-outlet の部分に出力される。

<!-- app.component.html -->

<router-outlet></router-outlet>

Angular FormControl

FormGroup を使わないパターン。

export class AppComponent {
  foo = new FormControl('foo-desu', [
    Validators.required,
  ])
}
<input [formControl]="foo">
<div>value: {{foo.value}}</div>
<div>error: {{foo.errors | json}}</div>


FormGroup を使うパターン。

export class AppComponent {
  constructor(private builder: FormBuilder) {}
  foo = new FormControl('foo-desu', [
    Validators.required,
  ])
  metaForm = this.builder.group({
    foo: this.foo
  })
}
<form [formGroup]="metaForm">
<input [formControl]="foo">
<div>input_value: {{foo.value}}</div>
<div>input_error: {{foo.errors | json}}</div>
<div>form_value: {{metaForm.controls.foo.value}}</div>
<div>form_error: {{metaForm.controls.foo.errors | json}}</div>
</form>