无法在KOA中设置标题使用回调时

MBe*_*mam 3 callback node.js koa

最近我参与了一个使用javascript回调的新项目.我正在使用koa框架.但是当我打电话给这条路线时:

function * getCubes(next) {
  var that = this;
     _OLAPSchemaProvider.LoadCubesJSon(function(result) {
    that.body = JSON.stringify(result.toString());
     });
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

_http_outgoing.js:331
throw new Error('Can\'t set headers after they are sent.');
      ^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:331:11)
at Object.module.exports.set (G:\NAP\node_modules\koa\lib\response.js:396:16)
at Object.length (G:\NAP\node_modules\koa\lib\response.js:178:10)
at Object.body (G:\NAP\node_modules\koa\lib\response.js:149:19)
at Object.body (G:\NAP\node_modules\koa\node_modules\delegates\index.js:91:31)
at G:\NAP\Server\OlapServer\index.js:42:19
at G:\NAP\Server\OlapServer\OLAPSchemaProvider.js:1599:9
at _LoadCubes.xmlaRequest.success (G:\NAP\Server\OlapServer\OLAPSchemaProvider.js:1107:13)
at Object.Xmla._requestSuccess (G:\NAP\node_modules\xmla4js\src\Xmla.js:2110:50)
at Object.ajaxOptions.complete (G:\NAP\node_modules\xmla4js\src\Xmla.js:2021:34)
Run Code Online (Sandbox Code Playgroud)

ber*_*rdw 8

问题是您的异步​​调用LoadCubesJSon()需要一段时间才能返回,但Koa不知道这一点并继续控制流程.这基本上yield是为了什么.

"可屈服"的对象包括承诺,生成器和thunk(以及其他).

我个人更喜欢用'Q'库手动创建一个承诺.但是你可以使用任何其他的promise库或者node-thunkify创建一个thunk.

这是一个简短但有效的例子Q:

var koa = require('koa');
var q = require('q');
var app = koa();

app.use(function *() {
    // We manually create a promise first.
    var deferred = q.defer();

    // setTimeout simulates an async call.
    // Inside the traditional callback we would then resolve the promise with the callback return value.
    setTimeout(function () {
        deferred.resolve('Hello World');
    }, 1000);

    // Meanwhile, we return the promise to yield for.
    this.body = yield deferred.promise;
});

app.listen(3000);
Run Code Online (Sandbox Code Playgroud)

所以你的代码看起来如下:

function * getCubes(next) {
    var deferred = q.defer();

    _OLAPSchemaProvider.LoadCubesJSon(function (result) {
        var output = JSON.stringify(result.toString());
        deferred.resolve(output);
    });

    this.body = yield deferred.promise;
}
Run Code Online (Sandbox Code Playgroud)