Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

現在実装済みの API 仕様が一般的な Web 標準 API と異なる #1

Open
dynamis opened this issue Jun 19, 2020 · 8 comments

Comments

@dynamis
Copy link
Contributor

dynamis commented Jun 19, 2020

現在の API 仕様 (WebIDL):

enum ServiceName { "achex", "websocketin" , "websocket.in" , "scaledrone" };

[Exposed=(Window)]
interface RelayServer {
  constructor(ServiceName serviceName, USVString serviceToken);
  Promise<Channel> subscribe(optional USVString channelName);
}

interface Channel {
  readonly attribute USVString serverName;
  void onMessage(MessageHandler handler);
  void sendMessage(USVString or object );
};

callback interface MessageHandler {
  void handleMessage(object message);
};

うっかり見逃したのですが、 onMessage / sendMessage というイベントハンドラ名と送信メソッド名のペアは Extension API の runtime と共通の名称になっています
https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage

Window 間のメッセージに合わせるなら onmessage / postMessage で、通信経路としても使っている WebSocket のメッセージに合わせるなら onmessage / send です:

https://developer.mozilla.org/ja/docs/Web/API/WindowEventHandlers/onmessage
https://developer.mozilla.org/ja/docs/Web/API/Window/postMessage

https://developer.mozilla.org/ja/docs/Web/API/WebSocket/onmessage
https://developer.mozilla.org/ja/docs/Web/API/WebSocket/send

裏に WS を使っている以上は通信が切断されてしまうイベントのハンドリングもいずれ可能になるべきで(後述、別 issue)、それを考慮していない Window の onmessage/postMessage よりも WebSocket の onmessage/send のペアを採用するのが良さそうです。

(他には socket.io などの著名ライブラリにインターフェイスを揃えるという選択肢もありますが、今回はイベント種別を定義して送受信する API ではなくなったので on(eventName, function(message) { ... }) / emit(eventName, message) ではないと思っています)

メソッド名だけでなく、受け渡しされるオブジェクトの仕様が異なります。send(string) なのは構わない (ArrayBuffer/Blob/ArrayBufferView によるバイナリメッセージ対応は別の話とできる) のですが、登録したイベントハンドラ関数が受け取る引数が send(string) で送ったものをそのまま onmessage = function(string) { console.log(string) } で受けるのでは Window/WebSocket 仕様いずれとも異なります。

API をシンプルにすることも大事ですが、既存類似用途 API と似ているのに違う API というは罠になるのでここは他と同様に onmessage = function(event) { console.log(event.data) } で受け取るようにすべきではないでしょうか。

なお、WebSocket 同様に接続が切れた場合のハンドリングを可能にするなど非同期・不安定性を考えると結局 Channel は WebSocket 相当の機能が必要となる場面がありますが、そのような拡張対応については取り急ぎサクッと使うという場面には不要なので別 issue にします。

@kou029w
Copy link

kou029w commented Jun 19, 2020

Achex Serverなどは単純にWebSocket APIとして利用可能なのでそのままWebSocketを継承したオブジェクト(EventTargetを継承している)を公開するのが利用しやすいかもですね

@satakagi
Copy link
Contributor

onmessage/send のペアでいきましょうかね~

@dynamis
Copy link
Contributor Author

dynamis commented Jun 19, 2020

そのままWebSocketを継承したオブジェクト(EventTargetを継承している)を公開するのが利用しやすいかもですね

何だかんだ再発明すると辛いのでそれが楽な気もします。一方、WebSocket を継承してもいろんなメソッドの挙動を書き換えていくことになるがちゃんと意図した実装に出来るのかどうかは心配というかやってみないと分からないかも (既存の WebSocket 拡張ライブラリの実装例を見てみたい。自動再接続 WebSocket 拡張とか WebSocket の継承で作ったことがある気がするので可能そうに思うけど)。

取り急ぎという意味では今の実装から名前と受け取るオブジェクトの変更だけしておき、更にそれ以上の問題をどうするかはゆっくり WebSocket の継承で出来るか確認してからって感じですかね。

@satakagi
Copy link
Contributor

ひとまず関数名だけ
onMessage -> onmessage
sendMessage -> send
と単に変更したものを載せておきますね。

@dynamis
Copy link
Contributor Author

dynamis commented Jun 19, 2020

はい。イベントハンドラの登録も早めに

channel.onMessage(function (string) { console.log(string) }) 

から

channel.onmessage = function(event) { console.log(event.data) }

として既存 API と統一出来ると嬉しいです (逆に振るまいが統一されないなら名前を統一しても罠があるという本質的な問題解決にならない)。

関数を渡して登録する場合はちゃんと addEventListener の振る舞い (複数登録可能、返り値を使って removeEventListener もできるなど) をしたくなりますが、自前実装は色々面倒になるのでそこは渡邉さんの書くように WebSocket 継承する実装に直せるタイミングでサポートすれば良いのだろうと。

@satakagi
Copy link
Contributor

あ、そうだ、event.dataもありましたね。
とりあえず関数名変えたものにぜんぶおきかえましたよ

@satakagi
Copy link
Contributor

ちなみに、event.data以外のプロパティ、三つのサーバで共通なもの何かあるなら付けておいた方が良いと思いますが、何かあったですかね?

@dynamis
Copy link
Contributor Author

dynamis commented Jun 19, 2020

event.data以外のプロパティ、三つのサーバで共通なもの何かあるなら付けておいた方が良いと思いますが、何かあったですかね?

リレーサーバから得られるイベントで共通なものは特になかった気がします。Achex なんかは from/to があって送信元情報を付与したり出来そうですが、websocekt.in とかもうメッセージの文字列がそのまま生で ws に流れてるものもあるので。

messageEvent 仕様を見てもこれは入れておきたい的なものがあるかというと
https://html.spec.whatwg.org/multipage/comms.html#messageevent
server-sent events and cross-document messaging で含まれる origin / port とかはあっても良いかもですが、あまり本質的に必要・有意なものかというと無くても平気な気がします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants