Posted at

CoffeeScriptでPromiseを使ったときにハマった

More than 3 years have passed since last update.

Atomのプラグインを書こうとして,CoffeeScriptを書いていたらPromiseの使用中にハマった.

もう既に誰かが踏んだ地雷な気がするし,Qiitaに記事があると思ったが,見つからなかったのでメモがてら残しておく.


やりたい事とコード

CoffeeScriptを使って,次のようなPromiseの使用をしたかった.



  1. thenの引数関数内で,メンバへのアクセスをする


  2. thenの引数関数内で,resolverejectを使う

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"))

が,これを動かすと,@nundefinedとなり(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は触り始めたばっかりなので.