Utilizar chamadas de retorno Com nodejs no KOA
-
23-12-2019 - |
Pergunta
Recentemente, comecei a trabalhar em um novo projeto, e este projeto o uso de JavaScript retornos de chamada em nodejs.Agora vamos usar KOA mas o problema acontece quando tentamos usar ES6 Geradores e as chamadas de retorno.
//Calback function
function load(callback){
result = null;
//Do something with xmla4js and ajax
callback(result);
return result;
}
Agora em KOA Eu preciso chamar load
e a resposta json para o cliente assim que eu usar esse código abaixo :
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;
});
}
mas eu recebo este erro :
_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)
Solução
Só para esclarecer as coisas, vamos escrever o seu retorno como
//Calback function
function load(callback){
setTimeout(function() {
var result = JSON.stringify({ 'my': 'json'});
callback(/* error: */ null, result);
}, 500);
}
em Koa mundo, isso é chamado de thunk
, o que significa que é uma função assíncrona que tem apenas um argumento:uma chamada de retorno com o protótipo (err, res).você pode verificar https://github.com/visionmedia/node-thunkify para uma melhor explicação.
agora você tem que escrever o seu middleware com
function *loadJson(){
this.type = 'application/json';
this.body = yield load;
}
Outras dicas
isto é principalmente porque KOA é gerador de base, se a sua em cima do middleware ele não suporta chamadas de retorno.então, não se trata de espera para a função para terminar.a melhor solução seria a de converter a sua função em uma promessa.promessa de grandes obras com KOA.
Eu tinha um problema semelhante usando braintree (regular retornos de chamada) e de coa.Com base em seu código, a única mudança que eu precisava fazer era com a função de carga e como era chamado.
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);
}
A explicação por Jerônimo e Evan acima é absolutamente correto, e thunkify parece um adequado processo para automaticamente fazer.
Enquanto thunks foram uma boa idéia, a meu ver, um Promise
é a melhor abordagem de longo prazo.Muitas bibliotecas já estão se movendo para promete para assíncrono, em vez de o nó antigo padrão callback(err, data)
, e eles estão mortos-simples para embrulhar em torno de qualquer assíncrona do código para fazer uma promessa.Outros devs vão ter experiências com Promessas e, naturalmente, compreender o seu código, enquanto que a maioria teria que procurar o que é uma "conversão" é.
exemplo:aqui estou eu embrulho o ainda-não-promessa-com base jsdom em uma promessa, para que eu possa produzi-lo em minha koa gerador.
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);
Semanticamente, promessas e geradores de passar de mão em mão para realmente esclarecer código assíncrono.Um gerador pode ser re-introduzidos muitas vezes e de rendimento de vários valores, enquanto uma promessa significa "eu prometo que vou ter alguns dados para você mais tarde".Combinado, você receber uma das coisas mais úteis que cerca de Koa:a capacidade para produzir as duas promessas, síncrona e valores.
editar:aqui é o seu exemplo original lacrada com uma Promessa de retorno:
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 ignorar Koa built-in de manipulação de resposta, você pode definir explicitamente
this.respond = false
;.Use isto se você quiser escrever para as matériasres
objeto, em vez de deixar Koa manipular a resposta para você.
Cabeçalho já está escrito integrado de manipulação de resposta antes de seu retorno de chamada é chamado.