@ledsun blog

無味の味は佳境に入らざればすなわち知れず

fetchは非同期だった

ruby.wasmのrequire_relativeでfetchする - @ledsun blog で良い感じに require_relative をfetchに置き換えられました。

ところがfetchは非同期関数なのです。 次のようなRubyスクリプトがあります。

require_relative "a-1"
require_relative "a-2"

p 'a loaded!'

これを読み込みます。

読み込んだ順番

require_relative が終わる前にRubyスクリプトの続きが実行されます。

const _global = window as any;
// Fetches Ruby scripts instead of retrieving them from the filesystem.
_global.rb_require_relative = async (relative_feature) => {
  const url = encodeURI(relative_feature + ".rb");
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`Failed to fetch "${relative_feature}".`);
  }
  const rubyScript = await response.text();
  vm.eval(rubyScript);
};

vm.eval(`
  require "js"
  module Kernel
    def require_relative(relative_feature)
      JS.global.rb_require_relative(relative_feature)
    end
  end
`);

こんな感じの実装です。 fetchは非同期関数なので、rb_require_relative も非同期関数にしてあります。 つまりrb_require_relativeが完了する前に次のRubyスクリプトが実行されます。

さて、どうしましょうか?

  1. Rubyスクリプトで非同期関数を待ち合わせる方法を考える
  2. XMLHttpRequest を使う