3

koa 用の「koa-router」モジュールを使用しようとしているときに、以下のサンプル コード スニペットを見ました。

app.get('/users/:id', function *(next) {
  var user = yield User.findOne(this.params.id);
  this.body = user;
});

私の質問は、なぜyieldユーザー情報を取得する直前にあるのですか? 以下のようなコードが生成されないのはなぜですか? 大きな違いはありますか?

app.get('/users/:id', function *(next) {
  var user = User.findOne(this.params.id);
  this.body = user;
});
4

4 に答える 4

3

アスタリスクfunction *(){}が付いた関数はジェネレーター関数であり、キーワードを使用して関数内のフローを一時停止および再開できます。yield

利回りのないジェネレーター関数は役に立たず、それらは密接に関連しています。

koaの舞台裏では、すべての非同期操作を処理する co ライブラリによってジェネレーター関数が呼び出され、コールバック / promise をライブラリに抽象て、よりフラットでシンプルなコードを残します。

役立つと思われるジェネレーターを理解するためのスクリーンキャストを作成しました。

于 2014-12-23T23:27:02.413 に答える
1

body は、将来まで存在しない値に設定されるためです。

hereは、待機動作が Koa インフラストラクチャによって処理されるyield一種のキーワードと考えることができます。waitPromise を生成すると、Koa は Promise が満たされるのを待ってからnext()、Promise の解決された値を への引数として使用して、ジェネレーターを再度呼び出します (実際には、ジェネレーターに基づいてイテレーターを呼び出します)。nextつまり、割り当てられます。の左側の変数にyield.

したがって、この場合、DB 呼び出しを行い、結果の promise を Koa に譲り、Koa はそれが満たされるのを待ってから、変数userに割り当てられた満たされた値を返します。関数は次の yield まで、またはまで実行されます。底から落ちます。

同じリクエストで2 つの非同期タスクを処理する方法を考えると、より明確になる可能性があります。

app.get('/users/:id', function *(next) {
    var user = yield User.findOne(this.params.id);
    var data = yield someOtherAsynchronousTaskReturningProimse(user);
    this.body = data;
});

この場合、「トランポリンで上下にジャンプ」を 2 回行っています。

これをどのように考えるかによって、これを次のようなより読みやすいものとして扱うことができます

function handle(id) {
    User.findOne(id)
        .then(function(user) {
            someOtherAsynchronousTaskReturningPromise(user)
                .then(function(data) {
                    setDataIntoResponse(data);
                });
        });
}

いわゆる「コルーチン」ベースのアプローチの方がはるかに読みやすいことに同意していただけると思います。このアーキテクチャのもう 1 つの利点は、ミドルウェア/ハンドラーをyield...yield流行に合わせて記述できることに加えて、返された promise が解決されるのを待っている間に、Koa が他の有用なことを実行できることです。

于 2014-12-24T03:53:29.533 に答える
1

コアは知りません。しかし、ハーモニージェネレーター(ノード0.11から利用可能)を利用しているようです。

基本的に、最初の部分は次と同じです。

app.get('/users/:id', function *(next) {
  var self = this;
  User.findOne(this.params.id).then(function(user) {
    self.body = user;
  });
});

yield が取る promise が解決されると、yield は満たされた値を返し、そこからプログラムが再開されます。これfunction *(..)は (私の知る限り) yield を使用できる特別な構造でもあります。

于 2014-12-23T03:09:00.117 に答える