Pregunta

Recientemente yo trabajo en un nuevo proyecto y este proyecto de uso de JavaScript devoluciones de llamada en nodejs.Ahora vamos a utilizar KOA pero el problema ocurre cuando tratamos de utilizar ES6 Generadores y las devoluciones de llamada.

//Calback function
function load(callback){
  result = null;
  //Do something with xmla4js and ajax
  callback(result);
  return result;
}

Ahora en KOA Tengo que llamar a load y la respuesta json para el cliente por lo que utilizar este código siguiente :

router= require('koa-router');
app = koa();
app.use(router(app));

app.get('load',loadjson);

function *loadJson(){
  var that = this;
  load(function(result){
    that.body = result;
  });
}

pero me da 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:40: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:2113:50)
at Object.ajaxOptions.complete (G:\NAP\node_modules\xmla4js\src\Xmla.js:2024:34)
¿Fue útil?

Solución

Solo para aclarar las cosas, vamos a escribir su devolución de llamada como

//Calback function
function load(callback){
    setTimeout(function() {
        var result = JSON.stringify({ 'my': 'json'});
        callback(/* error: */ null, result);
    }, 500);
}

En KOA WORLD, esto se denomina thunk, lo que significa que es una función asíncrona que toma solo un argumento: una devolución de llamada con el prototipo (ERR, RES).Puede comprobar https://github.com/visionmedia/node-thunkify para una mejor explicación.

Ahora tiene que escribir su middleware con

function *loadJson(){
  this.type = 'application/json';
  this.body = yield load;
}

Otros consejos

Esto se debe principalmente a que KOA se basa en el generador, si está en la parte superior del middleware, no admite devoluciones de llamada.Así que no está esperando que la función terminara.La mejor solución sería convertir su función en una promesa.Promesa funciona muy bien con koa.

Tuve un problema muy similar usando Braintree (devoluciones de llamada regulares) y KOA.Sobre la base de su código, el único cambio que debía hacer era con la función de carga y cómo se llamaba.

router = require('koa-router');
app = koa();
app.use(router(app));

app.get('/load',loadjson);

function *loadJson(){
  this.body = yield load;
}

// Callback function
function load(callback) {
  // Prepare some data with xmla4js and ajax
  whatever_inputs = {...};
  final_method(whatever_inputs, callback);
}

La explicación de Jerome y Evan anteriormente es absolutamente correcta, y thunkify parece un proceso adecuadopara hacerlo automáticamente.

Mientras que los procesadores eran una buena idea, en mi opinión, un Promise es un mejor enfoque a largo plazo.Muchas bibliotecas ya se están moviendo a las promesas para asincrónico en lugar de la antigua nodo estándar callback(err, data), y ellos están muertos-simple para envolver alrededor de cualquier código asincrónico de hacer una promesa.Otros desarrolladores se tienen experiencias con Promesas y, naturalmente, entender el código, mientras que la mayoría tendría que buscar lo que es un "procesador" es.

por ejemplo,aquí estoy envolviendo el que aún no la promesa basada en jsdom en una promesa, así que se pueden producir en mi koa generador.

const jsdom = require('node-jsdom');
const koa = require('koa');
const app = koa();
​
app.use(function *() {
  this.body = yield new Promise((resolve, reject) => jsdom.env({
    url: `http://example.org${this.url}`,
    done(errors, { document }) {
      if (errors) reject(errors.message);
      resolve(`<html>${document.body.outerHTML}</html>`);
    },
  }));
});
​
app.listen(2112);

Semánticamente, las promesas y los generadores de van de mano en mano para que realmente aclarar código asincrónico.Un generador puede ser re-introducido muchas veces y el rendimiento de varios valores, mientras que una promesa significa "yo te prometo que voy a tener algunos datos para que más adelante".Combinado, se obtiene una de las cosas más útiles acerca de Koa:la capacidad para producir tanto las promesas y sincrónica de valores.

editar:aquí esta el ejemplo original envuelto con una Promesa de volver:

const router = require('koa-router');
const { load } = require('some-other-lib');
const app = koa();
app.use(router(app));

app.get('load', loadjson);

function* loadJson() {
  this.body = yield new Promise(resolve => {
    load(result => resolve(result));
  });
}

Para la derivación de Koa construido-en respuesta a la manipulación, se puede establecer de forma explícita this.respond = false;.Use esta opción si desea escribir en el raw res objeto en lugar de dejar Koa manejar la respuesta para usted.

Encabezado ya está escrito construido-en respuesta a la manipulación antes de su devolución de llamada se invoca.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top