0

koa.js を使用して、バックグラウンドで長時間実行されるジェネレーター関数を実行する API を作成しますが、ユーザーにトークンをすぐに送り返します。

その後、ユーザーはそのトークンを使用して、後でジョブのステータスを取得できます。

'use strict';
var generateToken = function(){
    //...
};

var processData = function *(data, token) {
    //...
    var a = yield analysis(data);
    console.log(a) // a is undefined
};

app.post('/process_data', validate, function *(next) {
    var token = generateToken();
    var that = this;
    setTimeout(function() {
        for (var i of processData(that.request.body, token)){
            continue;
        }
    });
    this.body = "this should return immediately " + token;
    return next;
});

setTimeout 内で実行すると、変数 'a' は保存されません。processData が通常の利回りとまったく同じように実行されるようにするにはどうすればよいですか?

4

2 に答える 2

3

長時間実行されるプロセスを、 Kueなどのジョブ キューで処理する必要があるでしょう。

httpポストでジョブをキューに入れます

次に、http get でジョブを確認します

あなたがやりたいと思うことの大まかな概要は次のとおりです。

var kue       = require('kue'),
    koa       = require('koa'),
    route     = require('koa-router'),
    thunkify  = require('thunkify'),
    parse     = require('co-body'),
    co        = require('co'),
    app       = koa(),
    jobs      = kue.createQueue();

app.use(route(app));

// turn callbacks into thunks for generators
var createJob = thunkify(jobs.create);
var findJob   = thunkify(kue.Job.get);

// Process the job here
jobs.process('longProcess', function(job, done){
    // do work in here
    // call done(err) when completed
    // EDIT: if you want to handle job using generators/yield
    // you could use a library like co
    co(function *(){
        var qs = yield doWork(job.data); 
        done();
      }).error(done);
});

// Queue/Start the Job here
app.post('/jobs', function *(){
  var body = yield parse(this);
  var job = yield createJob('longProcess', body);
  this.body = job.id;
});

// Check Status of job here
app.get('/jobs/:token', function *(){
  var job = yield findJob(this.params.token);
  this.body = job;
  // job.status === 'complete' || ...
});

app.listen(3000); 
于 2015-01-13T22:06:05.610 に答える
0

ソリューションを提供してくれた Bergi に感謝します。

app.post('/process_data', validate, function *(next) {
    var token = generateToken();

    co(processData(this.request.body, token));

    this.body = "this should return immediately " + token;
    return next;
});
于 2015-01-13T21:07:34.150 に答える