孤独プログラマー譚

孤独死が近い。

Angular Observable, Promiseの相互変換

ObservableもPromiseも、似たようなもんだと思ってます。

import { from as fromPromise } from 'rxjs';

const foo = this.http.get('http://localhost:3000/')
console.log(foo) // Observable
foo.subscribe(res => console.log(1, res))

const bar = foo.toPromise()
console.log(bar) // Promise
bar.then(res => console.log(2, res))

const baz = fromPromise(bar)
console.log(baz) // Observable
baz.subscribe(res => console.log(3, res))

test

" copy file path
command! -nargs=0 CopyFilePath call s:Clip(expand('%:p'))
nnoremap <space>f :CopyFilePath<CR>
command! -nargs=0 CopyDirPath call s:Clip(expand('%:p:h'))
nnoremap <space>d :CopyDirPath<CR>
command! -nargs=0 CopyCwd call s:Clip(getcwd())
nnoremap <space>c :CopyCwd<CR>
nnoremap <space>m :cd %:h<CR>:echo "CWD => " . getcwd()<CR>
function! s:Clip(data)
  let @*=a:data
  echo "clipped: " . a:data
endfunction

Promise then, catchの連結

以下のコードは、どのような出力になるか?

const promise = Promise.reject()
promise
.then(() => console.log(1))
.catch(() => console.log(2))
.then(() => console.log(3))
.catch(() => console.log(4))
.then(() => console.log(5))
.catch(() => console.log(6))


答えは「2, 3, 5」

初めの変数promiseは、rejectされたPromiseオブジェクト。
1のthenは、rejectされたPromiseオブジェクトだから通らない。
2のcatchは、rejectされたPromiseオブジェクトだから通る。
同時にreturnされたと見なされ、resolveされたPromiseオブジェクトが返却される。
3のthenは、resolveされたPromiseオブジェクトだから通る。
同時にreturnされたと見なされ、resolveされたPromiseオブジェクトが返却される。
4のcatchは、resolveされたPromiseオブジェクトだから通らない。
5のthenは、resolveされたPromiseオブジェクトだから通る。
同時にreturnされたと見なされ、resolveされたPromiseオブジェクトが返却される。
6のcatchは、resolveされたPromiseオブジェクトだから通らない。

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
という解釈でいいと思う。