سؤال

أعمل مؤخرًا على مشروع جديد ويستخدم هذا المشروع عمليات رد اتصال JavaScript في العقدة.الآن نستخدم كوا لكن المشكلة تحدث عندما نحاول استخدام مولدات 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);
}

في عالم كوا، وهذا ما يسمى أ thunk, مما يعني أنها دالة غير متزامنة تأخذ وسيطة واحدة فقط:رد اتصال مع النموذج الأولي (خطأ، الدقة).يمكنك التحقق https://github.com/visionmedia/node-thunkify للحصول على تفسير أفضل.

الآن عليك أن تكتب البرمجيات الوسيطة الخاصة بك باستخدام

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

نصائح أخرى

ويرجع ذلك أساسًا إلى أن KOA يعتمد على المولد، وإذا كنت في الجزء العلوي من البرنامج الوسيط فإنه لا يدعم عمليات الاسترجاعات.لذلك لا تنتظر انتهاء الوظيفة.الحل الأفضل هو تحويل وظيفتك إلى وعد.الوعد يعمل بشكل رائع مع KOA.

واجهت مشكلة مشابهة جدًا في استخدام Braintree (عمليات الاسترجاعات العادية) و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);
}

إن تفسير جيروم وإيفان أعلاه صحيح تمامًا thunkify تبدو وكأنها عملية مناسبة للقيام بذلك تلقائيًا.

في حين أن الشكر كان فكرة جميلة، من وجهة نظري أ Promise هو نهج أفضل على المدى الطويل.تنتقل العديد من المكتبات بالفعل إلى الوعود بعدم المزامنة بدلاً من معيار العقدة القديم callback(err, data), ، ومن السهل جدًا الالتفاف حول أي رمز غير متزامن لتقديم الوعد.سيكون لدى المطورين الآخرين تجارب مع Promises وسيفهمون التعليمات البرمجية الخاصة بك بشكل طبيعي، بينما سيتعين على معظمهم البحث عن معنى "thunk".

على سبيل المثالأنا هنا أقوم بتغليف jsdom الذي لم يستند إلى الوعد بعد في وعد، حتى أتمكن من تقديمه في مولد 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);

من الناحية الدلالية، تسير الوعود والمولدات جنبًا إلى جنب لتوضيح التعليمات البرمجية غير المتزامنة.يمكن إعادة إدخال المولد عدة مرات وينتج عدة قيم، بينما الوعد يعني "أعدك بأنني سأحصل على بعض البيانات لك لاحقًا".مجتمعة، تحصل على واحدة من أكثر الأشياء المفيدة حول Koa:القدرة على تحقيق كل من الوعود والقيم المتزامنة.

يحرر:إليك المثال الأصلي الخاص بك ملفوفًا بوعد بالعودة:

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؛.استخدم هذا إذا كنت تريد الكتابة إلى الخام res اعترض بدلاً من السماح لـ Koa بالتعامل مع الرد نيابةً عنك.

تمت كتابة الرأس بالفعل من خلال معالجة الاستجابة المضمنة قبل استدعاء رد الاتصال الخاص بك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top