2016-02-19 6 views
2

Мы разрабатываем приложение, в котором мы используем Firebase в качестве базы данных и выражаем как промежуточное программное обеспечение/бэкэнд для маршрутизации наших API RESTful, который используется нашим Front-end, разработанным в Reactjs.FIREBASE ПРЕДУПРЕЖДЕНИЕ: Исключение было вызвано обратным вызовом пользователя. Ошибка: не удается установить заголовки после их отправки.

Ниже то, что наш файл server.js выглядит следующим образом:

var express = require('express'); 
var app = express(); 

//Used for getting POST variables from forms as well as query parameters 
var bodyParser = require('body-parser'); 
var validator = require('express-validator'); 

//Contains all the routes 
var routes = require('./routes/routes'); 
var path = require('path'); 

//Used for serving jade files 
app.set('view engine', 'jade'); 
//For serving static resources like scripts, styleSheets, html 
app.use(express.static(__dirname + '/views')); 

app.all('/*', function(req, res, next) { 
res.header("Access-Control-Allow-Origin", "*"); 
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept"); 
res.header("Access-Control-Allow-Methods", "POST, GET"); 
next(); 
}); 

// configure app to use bodyParser() 
// this will let us get the data from a POST 
app.use(bodyParser.urlencoded({ extended: true })); 
app.use(bodyParser.json()); 

app.use(validator({ 
    customValidators: { 
     onlyAlphabets: function(value) { 
      if (value.match('^[a-zA-Z ]*$')) { 
       return true; 
      } else { 
       return false; 
      } 
     }, 
     password: function(value) { 
      if (value.length >= 6 && value.length <=25 && value.match('^[\x20-\x7F]*$')) { 
       return true; 
      } else { 
       return false; 
      } 
     } 
    } 
})); 
app.use(routes); 

var port = process.env.PORT || 8080; //Set our port 

app.listen(port); 
console.log('Magic happens on port ' + port); 

Ниже приведен код для маршрутизации, который присутствует в route.js:

var express = require('express'); 
var views = __dirname; 
// Node.js path library - https://nodejs.org/api/path.html 
var path = require('path'); 
var Firebase = require("firebase"); 
var myFirebaseRef = new Firebase("https://crackling-inferno-8454.firebaseio.com/vendor_details"); 
var router = express.Router(); 
//Password Encryption and decryption helpers 
var hashFunction = require('../helpers/encrypt'); 


// middleware to use for all requests 
router.use(function(req, res, next) { 
    // do logging 
    console.log('Something is happening.'); 
    next(); // make sure we go to the next routes and don't stop here 
}); 

router.get('/', function(req, res) { 
    res.render('vendor_form'); 
}); 

router.route('/get_vendors').get(function(request, response) { 
    myFirebaseRef.on("value", function(snapshot) { 
     var store = snapshot.val(); 
     // Looping to get the firebaseId generated while push 
     for(var key in store){ 
      store[key].id = key; // Store firebaseID generated during push to store in JSON object 
     } 
     response.send(Object.keys(store).map(function(k) { return store[k]; })); 
    }, function (errorObject) { 
     response.send("The read failed: " + errorObject.code); 
    }); 
}); 

router.route('/post_vendor').post(function(request, response) { 

    request.checkBody({ 
     'vendor_name': { 
      notEmpty : { 
       errorMessage: 'Please enter a vendor\'s name' 
      }, 
      onlyAlphabets : { 
       errorMessage: 'Please enter only alphabets' 
      } 
     }, 
     'enterprise_name': { 
      notEmpty : { 
       errorMessage: 'Please enter an enterprise\'s name' 
      }, 
      onlyAlphabets : { 
       errorMessage: 'Please enter only alphabets' 
      } 
     }, 
     'vendor_email': { 
      notEmpty : { 
       errorMessage: 'Please enter your email address' 
      }, 
      isEmail : { 
       errorMessage: 'please enter an appropriate email format' 
      } 
     }, 
     'vendor_password': { 
      notEmpty : { 
       errorMessage: 'Please enter a password' 
      }, 
      password: { 
       errorMessage: 'Password length should be between 6-25 characters' 
      } 
     }, 
     'food_preference': { 
      notEmpty: { 
       errorMessage: 'You must select atleast one food preference' 
      } 
     } 
    }); 

    var errors = request.validationErrors(); 

    // var onComplete = function(error) { 
    // if (error) { 
    //  response.send('Failed to add stats to the database'); 
    //  return false; 
    // } else { 
    //  // response.render('vendor_form', { success: true }); 
    //  response.send('Success'); 
    //  return true; 
    // } 
    // }; 

    if (errors) { 
     response.send(errors); 
     // response.render('vendor_form', { error: errors }); 
     return false; 
    } else { 
     myFirebaseRef.push().set({ 
      'id': Firebase.ServerValue.TIMESTAMP, 
      'vendor_name': request.body.vendor_name, 
      'enterprise_name': request.body.enterprise_name, 
      'vendor_email': request.body.vendor_email, 
      'vendor_password': hashFunction.encrypt(request.body.vendor_password), 
      'food_preference': request.body.food_preference 
     }, function(err) { 
     if (err) { 
     response.send('Failed to add stats to the database'); 
     } else { 
     response.send('Success'); 
     } 
    }); 
    return true; 
    } 
}); 

module.exports = router; 

Ниже приведен код, мы добавили в интерфейсе для размещения данных. Мы также используем WHATWG-выборки пакета:

httpservice.js:

var Fetch = require('whatwg-fetch'); 
var baseUrl = 'http://192.168.1.134:8080'; 

var Service = { 
    get: function(url) { 
    console.log('MAKING A GET REQUEST'); 
    return fetch(baseUrl + url) 
    .then(function(response) { 
     return response.json(); 
    }); 
    }, 

    post: function(url, postData) { 
    console.log('MAKING A POST REQUEST'); 
    return fetch(baseUrl + url, { 
     headers: { 

     'Content-Type': 'application/json' 
     }, 
     method: 'POST', 
     body: JSON.stringify(postData) 
    }).then(function(response) { 
     return response; 
    }); 
    } 
} 

module.exports = Service; 

VendorForm.js (React файл компонента)

HTTP.post('/post_vendor', httpRequestBody) 
.then(function(response) { 
     console.log(response); 
}.bind(this)); 

Мы начинаем наш сервер, который предоставляет RESTful API, разработанный в FIREBASE + EXPRESS через nodemon. Это ошибка, которую мы получаем, когда мы размещаем наши:

FIREBASE WARNING: Exception was thrown by user callback. Error: Can't set headers after they are sent. 
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11) 
    at ServerResponse.header (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:718:10) 
    at ServerResponse.send (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:163:12) 
    at ServerResponse.json (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:249:15) 
    at ServerResponse.send (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:151:21) 
    at /var/www/tutorials/express_firebase/routes/routes.js:30:12 
    at /var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:200:710 
    at ec (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:52:165) 
    at ac (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:31:216) 
    at bc (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:30:1259) 
    at Ji.h.Mb (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:220:440) 
    at X.set (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:256:335) 
    at /var/www/tutorials/express_firebase/routes/routes.js:96:24 
    at Layer.handle [as handle_request] (/var/www/tutorials/express_firebase/node_modules/express/lib/router/layer.js:95:5) 
    at next (/var/www/tutorials/express_firebase/node_modules/express/lib/router/route.js:131:13) 
    at Route.dispatch (/var/www/tutorials/express_firebase/node_modules/express/lib/router/route.js:112:3) 
/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:52 
(d="0"+d),c+=d;return c.toLowerCase()}var zd=/^-?\d{1,10}$/;function td(a){return zd.test(a)&&(a=Number(a),-2147483648<=a&&2147483647>=a)?a:null}function ec(a){try{a()}catch(b){setTimeout(function(){R("Exception was thrown by user callback.",b.stack||"");throw b;},Math.floor(0))}}function S(a,b){if(t(a)){var c=Array.prototype.slice.call(arguments,1).slice();ec(function(){a.apply(null,c)})}};function Ad(a){var b={},c={},d={},e="";try{var f=a.split("."),b=Pb(id(f[0])||""),c=Pb(id(f[1])||""),e=f[2],d=c.d||{};delete c.d}catch(g){}return{oh:b,Dc:c,data:d,ah:e}}function Bd(a){a=Ad(a).Dc;return"object"===typeof a&&a.hasOwnProperty("iat")?z(a,"iat"):null}function Cd(a){a=Ad(a);var b=a.Dc;return!!a.ah&&!!b&&"object"===typeof b&&b.hasOwnProperty("iat")};function Dd(a){this.Y=a;this.g=a.n.g}function Ed(a,b,c,d){var e=[],f=[];Na(b,function(b){"child_changed"===b.type&&a.g.Ad(b.Le,b.Ma)&&f.push(new H("child_moved",b.Ma,b.Ya))});Fd(a,e,"chi 

Error: Can't set headers after they are sent. 
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11) 
    at ServerResponse.header (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:718:10) 
    at ServerResponse.send (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:163:12) 
    at ServerResponse.json (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:249:15) 
    at ServerResponse.send (/var/www/tutorials/express_firebase/node_modules/express/lib/response.js:151:21) 
    at /var/www/tutorials/express_firebase/routes/routes.js:30:12 
    at /var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:200:710 
    at ec (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:52:165) 
    at ac (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:31:216) 
    at bc (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:30:1259) 
    at Ji.h.Mb (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:220:440) 
    at X.set (/var/www/tutorials/express_firebase/node_modules/firebase/lib/firebase-node.js:256:335) 
    at /var/www/tutorials/express_firebase/routes/routes.js:96:24 
    at Layer.handle [as handle_request] (/var/www/tutorials/express_firebase/node_modules/express/lib/router/layer.js:95:5) 
    at next (/var/www/tutorials/express_firebase/node_modules/express/lib/router/route.js:131:13) 
    at Route.dispatch (/var/www/tutorials/express_firebase/node_modules/express/lib/router/route.js:112:3) 
[nodemon] app crashed - waiting for file changes before starting... 

По ошибке, мы знаем, что некоторые обратного вызова установки заголовка дважды, но не уверен, как это происходит. Был через несколько вопросов переполнения стека, но до сих пор не нашел решения. Любая помощь будет оценена по достоинству. Спасибо в ожидании.

+1

Выполняется ли 'myFirebaseRef.on (« значение », fn)' огонь более одного раза? –

+0

@BenFortune Согласно вашему предложению, я сделал консоль внутри myFirebaseRef.on ("value", fn). Он работает отлично на некоторое время. Но когда он падает, перед сбоем console.log() вызывается дважды. Это означает, что функция вызывается дважды. Но приложение падает на POST. Мы написали myFirebaseRef.on («значение», fn) <--- функция для get. Полностью смущен, что происходит. Спасибо, что указали эту штуку, хотя и жаль, что ответили поздно. –

ответ

4

Если вы видите ваш трассировки стека

at /var/www/tutorials/express_firebase/routes/routes.js:30:12 

Какая строка 30 в route.js файле

response.send(Object.keys(store).map(function(k) { return store[k]; })); 

Вам нужно изменить метод on для once, в противном случае ваша функция обратного вызова получает срабатывает каждый раз, когда обновлено до ваших данных,

router.route('/get_vendors').get(function(request, response) { 
    myFirebaseRef.on("value", function(snapshot) { 

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

См эталонным https://firebase.google.com/docs/database/server/retrieve-data#section-reading-once

В основном то, что вы делаете с помощью метода once является удаление обратного вызова сразу же после того, как значение считывается.

+0

Была такая же проблема. Идеальное исправление и смысл в простой замене на один раз сделал трюк для меня тоже! –

 Смежные вопросы

  • Нет связанных вопросов^_^