CoffeeScriptでPromiseを使ったときにハマった
Qiitaからの移動
Atomのプラグインを書こうとして,CoffeeScriptを書いていたらPromise
の使用中にハマった.
もう既に誰かが踏んだ地雷な気がするし,Qiitaに記事があると思ったが,見つからなかったのでメモがてら残しておく.
やりたい事とコード
CoffeeScriptを使って,次のようなPromise
の使用をしたかった.
then
の引数関数内で,メンバへのアクセスをするthen
の引数関数内で,resolve
,reject
を使う
then
内で,非同期APIの結果の例外処理(JSON,DOMのパースなど)をして,さらに,成功時はメンバへアクセスして処理をするような感じで,例えば,次のようなコード(Promise
の必要がないコードだが,例という事で)
class Class
n: 2
func: ->
new Promise(
(resolve) -> resolve(10)
).then(
(value) ->
if value is 0
reject("value is 0")
else
resolve(value * @n)
).then((value) -> console.log(value + " #result"))
が,これを動かすと,@n
がundefined
となり(CoffeeScriptの仕様への自分の理解が正しければ当然),コンソールにはNaN #result
が表示されてしまう.
こういうcallbackを簡単にかくために,CoffeeScriptには=>
という記法があるので,これを使うと次のように書ける.
class Class
n: 2
func: ->
new Promise(
(resolve) -> resolve(10)
).then(
(value) =>
if value is 0
reject("value is 0")
else
resolve(value * @n)
).then((value) -> console.log(value + " #result"))
しかし,今度はUncaught (in promise) ReferenceError: resolve is not defined
というエラーメッセージが表示される.
あまりちゃんと調べていないが,resolve
は,this.resolve
の意味であり,=>
によってthis
の動きが変わっているのだろう.
実験
どういうふうに書けば適切な動作をするのかを調べるべく,書き方を思いつく限り試して見た所,次のような結果になった.結局,new Promise
を使って記述するのが今回の場合は最善なのかな.
上手く動くコード
then((value) -> value)
then((value) => value * @n)
then((value) => new Promise((resolve, reject) => resolve(value * @n))
メンバにアクセス出来ずに変な動作をするコード
then((value) -> value * @n)
ReferenceErrorが起こるコード
(value) => resolve(value * @n)
最後に
他にもっと簡単な解決策があれば教えて頂けると嬉しいです.CoffeeScriptは触り始めたばっかりなので.