Вопрос

Недавно я работаю над новым проектом, и в этом проекте используются обратные вызовы JavaScript в nodejs.Теперь мы используем КОА но проблема возникает, когда мы пытаемся использовать генераторы ES6 и обратные вызовы.

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

Сейчас в КОА мне нужно позвонить load и ответьте клиенту в формате json, поэтому я использую этот код ниже:

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

но я получаю эту ошибку:

_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)
Это было полезно?

Решение

Просто чтобы уточнить вещи, давайте напишем ваш обратный вызов как

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

в мире KOA, это называется генеракодицетагкодом, что означает, что это асинхронная функция, которая принимает только один аргумент: обратный вызов с прототипом (ERR, RES).Вы можете проверить https://github.com/visionmedia/node-thingsify для лучшего объяснения.

Теперь вы должны написать свое промежуточное программное обеспечение с помощью

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

Другие советы

Это в основном потому, что KOA является генератором на основе генератора, если вы на вершине промежуточного программного обеспечения он не поддерживает обратные вызовы.Так что это не ждет функции, чтобы закончить.Лучшее решение было бы преобразовать вашу функцию в обещание.Обещание работает отлично с коа.

У меня была очень похожая проблема, используя BreAntree (регулярные обратные вызовы) и KOA.Исходя из вашего кода, единственное изменение, которое мне нужно было сделать, было с функцией нагрузки и как его называли.

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

Объяснение Джерома и Эван выше, абсолютно правильно, и Thuscify выглядит как подходящий процессДля автоматического сделать это.

Хотя «спасибо» было хорошей идеей, на мой взгляд, Promise это лучший долгосрочный подход.Многие библиотеки уже переходят на промисы для асинхронности вместо старого стандарта узлов. callback(err, data), и их очень просто обернуть вокруг любого асинхронного кода, чтобы дать обещание.Другие разработчики будут иметь опыт работы с промисами и, естественно, поймут ваш код, в то время как большинству придется искать, что такое «thunk».

напримерздесь я заключаю jsdom, основанный на еще не обещаниях, в обещание, чтобы я мог передать его в своем генераторе коа.

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

Семантически промисы и генераторы идут рука об руку, чтобы действительно прояснить асинхронный код.Генератор можно вводить повторно много раз и выдавать несколько значений, а обещание означает: «Я обещаю, что позже у меня будут для вас некоторые данные».В совокупности вы получаете одну из самых полезных вещей о Коа:способность давать как обещания, так и синхронные значения.

редактировать:вот ваш исходный пример, завернутый в обещание вернуться:

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

Чтобы обойти встроенную обработку ответов KOA, вы можете явно установить this.respond = false;.Используйте это, если вы хотите написать на объект RAW res вместо того, чтобы KOA обратимся к ответу для вас.

заголовок уже написан встроенным обращением о обращении, прежде чем ваш обратный вызов будет вызван.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top