tutorial node desde cero javascript node.js callback koa

javascript - desde - Usar devoluciones de llamada con nodejs en KOA



node js desde cero pdf (5)

Recientemente, trabajo en un nuevo proyecto y este proyecto utiliza devoluciones de llamada de JavaScript en nodejs. Ahora usamos KOA, pero el problema ocurre cuando tratamos de usar generadores ES6 y devoluciones de llamadas.

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

Ahora en KOA necesito llamar a load y response json al cliente, entonces uso este código a continuación:

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


Solo para aclarar las cosas, escribamos 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 el mundo de Koa, esto se denomina thunk , lo que significa que es una función asincrónica que solo tiene un argumento: una devolución de llamada con el prototipo (err, res). puede consultar https://github.com/visionmedia/node-thunkify para obtener una mejor explicación.

ahora tienes que escribir tu middleware con

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


Para eludir el manejo de respuesta integrado de Koa, puede establecer explícitamente this.respond = false ;. Úselo si desea escribir en el objeto res procesar en lugar de dejar que Koa maneje la respuesta por usted.

El encabezado ya está escrito por el manejo de respuesta incorporado antes de que se invoque su devolución de llamada.


esto se debe principalmente a que KOA está basado en un generador; si está en la parte superior del middleware, no admite devoluciones de llamadas. entonces no está esperando que termine la función. La mejor solución sería convertir su función en una promesa. la promesa funciona muy bien con KOA.


Tuve un problema muy similar al usar braintree (devoluciones de llamada regulares) y koa. De acuerdo con su código, el único cambio que tenía que 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 anterior es absolutamente correcta, y thunkify parece un proceso adecuado para hacerlo automáticamente.


Aunque los thunks fueron una buena idea, en mi opinión una Promise es un mejor enfoque a largo plazo. Muchas bibliotecas ya se están moviendo a las promesas de asincronización en lugar de la callback(err, data) estándar del antiguo nodo callback(err, data) , y son muy sencillas para envolver cualquier código asíncrono para hacer una promesa. Otros desarrolladores tendrán experiencias con Promises y naturalmente comprenderán tu código, mientras que la mayoría debería buscar lo que es un "thunk".

por ejemplo, aquí estoy envolviendo el jsdom no basado en promesas en una promesa, así que puedo cederlo en mi generador de koa.

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 van de la mano para aclarar realmente el código asíncrono. Un generador puede ser reingresado muchas veces y arrojar varios valores, mientras que una promesa significa "Prometo que tendré algunos datos para usted más tarde". Combinados, obtienes una de las cosas más útiles sobre Koa: la capacidad de generar tanto promesas como valores sincrónicos.

editar: aquí está su ejemplo original envuelto con una promesa de devolución:

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