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)
Foi útil?

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érias res 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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top