No se puede establecer el encabezado en KOA cuando se utiliza la callback

Recientemente trabajé en un nuevo proyecto que usaba devoluciones de llamada javascript. Y estaba usando koa framework. Pero cuando llamé a esta ruta:

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

Me sale este error:

 _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) 

El problema es que su llamada asíncrona LoadCubesJSon() tarda un poco en volver, pero Koa no es consciente de eso y continúa con el flujo de control. Eso es básicamente para lo que es el yield .

Los objetos “rendibles” incluyen promesas, generadores y generos (entre otros).

Personalmente prefiero crear manualmente una promesa con la biblioteca ‘Q’ . Pero puede usar cualquier otra biblioteca de promesa o node-thunkify para crear un procesador.

Aquí está el ejemplo corto pero de trabajo con 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); 

Para que su código se vea como sigue:

 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; }