LoginSignup
4
3

More than 1 year has passed since last update.

【JavaScript】第2引数でコールバックする関数をどうにかしたい

Last updated at Posted at 2020-02-17

とりあげる課題とその問題点

今回取り上げるものは以下のようなコード
実例はkuromoji.js

(A: T, B: VoidFunction) => void
kuromoji/example/load-node.js
"use strict";

var kuromoji = require("../src/kuromoji");
var DIC_DIR = "dict/";

// Load dictionaries from file, and prepare tokenizer
kuromoji.builder({ dicPath: DIC_DIR }).build(function (error, tokenizer) { // ここが問題のコールバック
    var path = tokenizer.tokenize("すもももももももものうち");
    console.log(path);
    module.exports = tokenizer;
});

// ここでtokenizerは使えない

このtokenizerはこのままではコールバック関数外では利用できない。
これはスコープの関係上当たり前だが、少々使いづらい。

しかもコールバック地獄の原因なので使いたくない

というわけでこれを

test
const kuromoji = await tokenizer();
const res = kuromoji
      .tokenize('すもももももももものうち')
      .map(t => t.surface_form);

expect(res).toEqual(['すもも', '', 'もも', '', 'もも', '', 'うち']);

このようにfunctionalに書きたい。

image.png

解決策

new promiseする

typescript
import kuromoji, { Tokenizer, IpadicFeatures, TokenizerBuilder } from 'kuromoji';

const builder: TokenizerBuilder<IpadicFeatures> = kuromoji.builder({
  dicPath: 'node_modules/kuromoji/dict',
});

export const tokenizer = () => new Promise<Tokenizer<IpadicFeatures>>(done => {
  builder.build((_err, tokenizer) => {
    done(tokenizer);
  });
});

こうすると

test
const kuromoji = await tokenizer();
const res = kuromoji
      .tokenize('すもももももももものうち')
      .map(t => t.surface_form);

expect(res).toEqual(['すもも', '', 'もも', '', 'もも', '', 'うち']);

まとめ

取り上げたコードの名称を「継続」っていうらしいです。
async/await世代なので少し詰まった。

参考文献

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3