I'm currently starting work for my bachelor thesis and recently started 'digging' into the use of node.js and webSocket. My webSocket server runs without problems when accessed in Firefox 15.0 and Chrome 21.0.1180.89 m. In Opera 12.02, there seems to be a problem with the client-server handshake. This is what Opera's error console says:
[31.08.2012 01:03:51] WebSockets - http://10.0.0.2/
Connection
WebSocket handshake failure, invalid response code '400'.
Funny thgough: I can't find this error anywhere in the Dragonfly console's network log. All the fields that are requested when accessing the website (index.html, client.js etc.) are found and served as they should be (HTTP Status code 200 OK). Also, the only status codes that my server returns are 200, 404 and 500, so this looks like it's coming from within webSocket itself.
And yes, webSocket IS enabled in Opera...I have no idea what the problem could be
Any help would be really appreciated :)
EDIT:
This is my code so far so you can see which headers my server sends and how I create webSocket connections with my client.js:
server.js:
// load required modules:
var http = require("http");
var WebSocketServer = require("websocket").server;
path = require("path");
url = require("url");
filesys = require("fs");
// declare listening port vars:
var httpListeningPort = 80;
var webSocketListeningPort = 80;
// create HTTP-server:
var httpSrv = http.createServer(function(request, response) {
console.log((new Date()) + ":\tReceived request for " + request.url);
// response.writeHead(200);
// response.end();
var myPath = url.parse(request.url).pathname;
var fullPath = path.join(process.cwd(), myPath);
if(myPath === "/") {
fullPath += "index.html";
console.log("Full path:\t" + fullPath);
filesys.readFile(fullPath, "binary", function(err, file) {
if(err) {
response.writeHeader(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
}
else {
response.writeHeader(200);
response.write(file, "binary");
response.end();
}
});
}
else {
path.exists(fullPath, function(exists) {
if(!exists) {
response.writeHeader(404, {"Content-Type": "text/plain"});
response.write("404 Not Found\n");
response.end();
}
else {
filesys.readFile(fullPath, "binary", function(err, file) {
if(err) {
response.writeHeader(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
}
else {
response.writeHeader(200);
response.write(file, "binary");
response.end();
}
});
}
});
}
});
httpSrv.listen(httpListeningPort, function() {
console.log((new Date()) + ":\tServer is now listening on port " + httpListeningPort);
});
// create webSocket server and tie it to the http server:
wsServer = new WebSocketServer({
httpServer: httpSrv
});
function originChecker(origin) {
if(origin) {
console.log("Origin " + origin + " is allowed");
return true;
} else {
console.log("origin is NOT allowed.");
return false;
}
}
// how to handle requests:
wsServer.on("request", function(request) {
// check whether origin is allowed or not:
if(originChecker(request.origin) === false) {
request.reject();
console.log((new Date()) + ":\tConnection request from origin " + request.origin + " rejected.");
return;
}
// accept the connecteion request -> open the connection:
var connection = request.accept(null, request.origin);
console.log((new Date()) + ":\tConnection request from " + request.origin + " accepted.");
// handle incoming messages from the clients:
connection.on("message", function(message) {
if(message.type === "utf8") {
console.log((new Date()) + ":\tReceived message from " + request.origin + ":\nType: " + message.type + "\nLength: " + message.utf8Data.length + "\nMessage: " + message.utf8Data);
// echo "Message received":
connection.sendUTF(JSON.stringify( { type: "message", data: "Message received !" } ));
} else {
// send error message back to client:
console.log((new Date()) + ":\tReceived message from " + request.origin + ":\nERROR:\tMessage is NOT UTF-8! it's " + message.type);
connection.sendUTF(JSON.stringify( { type: "message", data: "ONLY UTF-8 accepted !" } ));
}
});
// what to do when connection is closed:
connection.on("close", function() {
console.log((new Date()) + ":\tClient #" + connection.remoteAddress + " disconnected.");
});
});
client.js:
function client() {
if("WebSocket" in window) {
alert("WebSocket is supported by your browser!");
// try to connect to the webSocket server:
var connection = null;
connection = new WebSocket("ws://10.0.0.2:80");
// things to do once the connection is opened:
connection.onopen = function() {
alert("INFO:\tConnection to server is OPEN");
document.getElementById("msgInput").focus();
document.getElementById("msgInput").disabled = false;
document.getElementById("msgInput").value = "";
document.getElementById("msgInput").onkeyup = function(key) {
switch(key.keyCode) {
case 13: if(document.getElementById("msgInput").value === "") {
break;
}
var messageText = document.getElementById("msgInput").value;
document.getElementById("msgInput").disabled = true;
document.getElementById("msgInput").value = "";
document.getElementById("statusHeader").innerHTML = "Sending...";
connection.send(messageText);
break;
default: document.getElementById("statusHeader").innerHTML = "Press ENTER to send!";
}
};
};
connection.onerror = function(error) {
document.body.style.backgroundColor = "#220000";
document.body.style.color = "#aa0000";
document.getElementById("statusHeader").innerHTML = "ERROR connecting to server -> OFFLINE";
return;
};
connection.onmessage = function(message) {
try {
var json = JSON.parse(message.data);
} catch (error) {
alert("ERROR parsing message:\t" + error);
return;
}
document.getElementById("statusHeader").innerHTML = json.data;
document.getElementById("msgInput").disabled = false;
};
connection.onclose = function() {
setTimeout(function() {
document.body.style.backgroundColor = "#808080";
document.body.style.color = "#ffffff";
document.getElementById("statusHeader").innerHTML = "OFFLINE";
document.getElementById("msgInput").disabled = true;
document.getElementById("msgInput").value = "OFFLINE";
}, 5000);
return;
};
} else {
alert("WebSocket is NOT supported by your browser! Exiting now.");
return;
}
};
According to a recent question Opera 12 supports an older, incompatible version of websockets. This version (Hixie-76) uses a different set of headers in its handshake. Your server presumably doesn't understand these which explains its 400 error response.
If you can afford to wait for Opera to catch up, the easiest 'solution' is to use other browsers for your testing for now. The hixie protocol drafts are deprecated so Opera is bound to upgrade to RFC 6455 eventually.
Related
I am trying to insert the sensor data into a SQL Server database. I have tried all the possible way to insert the incoming data into database, but I failed. I am new to Nodejs and I really have no idea why these errors are occurred during executing process. It would be great if anyone could help me.
Thank you in advance.
The error I get is:
TypeError: Cannot read property 'writeHead' of undefined.
function addData (req, resp, reqBody, data)
{
try {
if (!reqBody) throw new Error("Input not valid");
data = JSON.parse(reqBody);
//reqBody = JSON.parse(data);
if (data) {//add more validations if necessary
var sql = "INSERT INTO arduinoData (Machine, StartTime, EndTime, LengthTime) VALUES ";
sql += util.format("(%s, '%s', %s, %s) ", data.Machine, data.StartTime, data.EndTime, data.LengthTime);
db.executeSql(sql, function (data, err) {
if (err) {
httpMsgs.show500(req, resp, err);
}
else {
httpMsgs.send200(req, resp);
}
});
}
else {
throw new Error("Input not valid");
}
}
catch (ex) {
httpMsgs.show500(req, resp, ex);
}
};
function sendBackupData()
{
var jsonTable = { "table": [] };
fs.readFile("backup.json", "utf8", function (err, data) {
if (err) throw err;
jsonTable = JSON.parse(data);
if (jsonTable.table.length == 0) {
return;
}
for (var index = 0; index < jsonTable.table.length; index++) {
var options = {
url: serverURL,
method: "POST",
form: jsonTable.table.shift()
};
request.post(options, function (error, response, body) {
if (!error) {
console.log("Sent backup message!");
} else {
console.log('Error: ' + error);
console.log("CANT'T SEND BACK");
console.log(options.form);
jsonTable.table.push(options.form);
}
});
}
var outputJSON = JSON.stringify(jsonTable);
console.log(outputJSON);
fs.writeFile("backup.json", outputJSON, "utf8", function (err) {
if (err) throw err;
console.log("Sent backup data!");
});
});
}
function getTime()
{
var date = new Date();
var year = date.getFullYear();
var month = ('0' + (date.getMonth() + 1)).slice(-2);
var day = ('0' + date.getDate()).slice(-2);
var hour = ('0' + date.getHours()).slice(-2);
var minute = ('0' + date.getMinutes()).slice(-2);
var second = ('0' + date.getSeconds()).slice(-2);
// Unix Time
var unixTime = Math.floor(date / 1000);
// Check if it is day or night
var isDay;
if (date.getHours() >= 8 & date.getHours() < 16)
{
isDay = true;
}
else
{
isDay = false;
}
return [year + '-' + month + '-' + day, hour + ':' + minute + ':' + second, unixTime, isDay];
}
/*
--- Main Code ---
*/
function vibrationStart()
{
/*
Should get:
- Start time and date the vibration started
- Whether it was day or night
Will send the message, if there is network connection, once complete.
Will store message into a JSON file if there is no network connection.
*/
var jsonTable = { "table": [] };
var startTime = getTime();
console.log(startTime[0] + " " + startTime[1]);
var startData = {
machine: machineName,
start_time: startTime[0] + " " + startTime[1],
day_night: startTime[3],
active: "true"
};
const options = {
url: serverURL,
method: "POST",
form: startData
};
var reqBody = [{
Machine : "",
StartTime : ""
}];
reqBody.push({"Machine" : startData.machine,"StartTime" : startData.start_time});
var outputJSON = JSON.stringify(reqBody);
request.post(options, function (error, response, body) {
if (!error) {
console.log("Sent starting message!");
sendBackupData();
addData();
} else {
console.log("CANT'T SEND");
// Write to JSON file for backup if can't send to server
fs.readFile("backup.json", "utf8", function readFileCallback(err, data) {
if (err) throw err;
jsonTable = JSON.parse(data);
jsonTable.table.push(startData);
var outputJSON = JSON.stringify(jsonTable);
fs.writeFile("backup.json", outputJSON, "utf8", function (err) {
if (err) throw err;
});
});
}
});
return startTime[2];
}
function vibrationStop(startTimeUnix)
{
var jsonTable = { "table": [] };
var endTime = getTime();
console.log(endTime[0] + " " + endTime[1]);
var endTimeUnix = endTime[2];
var lengthTime = endTimeUnix - startTimeUnix;
console.log("Length time: " + lengthTime);
var endData = {
machine: machineName,
end_time: endTime[0] + " " + endTime[1],
length_time: lengthTime,
active: "false"
};
const options = {
url: serverURL,
method: "POST",
form: endData
};
var reqBody = [{
EndTime : "",
LengthTime :"",
}];
reqBody.push({"EndTime" : endData.end_time,"LengthTime" : endData.length_time});
var outputJSON = JSON.stringify(reqBody);
request.post(options, function (error, response, body) {
if (!error) {
console.log("Sent end message!");
sendBackupData();
addData()
} else {
console.log("CANT'T SEND");
// Write to JSON file for backup if can't send to server
fs.readFile("backup.json", "utf8", function readFileCallback(err, data) {
if (err) throw err;
jsonTable = JSON.parse(data);
jsonTable.table.push(endData);
var outputJSON = JSON.stringify(jsonTable);
fs.writeFile("backup.json", outputJSON, "utf8", function (err) {
if (err) throw err;
});
});
}
});
}
http.createServer(function (req, resp) {
app.get('/', addData);
}).listen(settings.webPort, function () {
console.log("Started listening at: " + settings.webPort);
});
The idea of what I'm currently doing is that you can take a photo or select one from the gallery and upload it to a server. I was having trouble with using the cordova FileTransfer to send and upload the image. It was either not sending at all or $_FILES["file"] would be empty.
I have separate buttons to bring up the camera and gallery:
<button id="takePicture" name="takePicture" ng-click="openCamera();">Take Photo</button>
<button id="getPicture" name="getPicture" ng-click="openGallery();">Choose From Gallery</button>
Solution:
$scope.openCamera = function()
{
navigator.camera.getPicture(onSuccess, onError,
{ quality : 100,
destinationType : Camera.DestinationType.FILE_URI
});
function onSuccess(imageURI)
{
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = imageURI.substr(imageURI.lastIndexOf("/")+1);
options.mimeType = "image/jpeg";
options.httpMethod = "POST";
options.chunkedMode = false;
options.params = { filePath : imageURI.split("?")[0] };
var fileTransfer = new FileTransfer;
fileTransfer.upload(imageURI, encodeURI("upload.php"), uploadComplete, uploadError, options);
function uploadComplete(result)
{
console.log("Code = " + result.responseCode);
console.log("Response = " + result.response);
console.log("Sent = " + result.bytesSent);
}
function uploadError(error)
{
alert("An error has occurred: Code = " + error.code);
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}
}
function onError(message)
{
alert("fail");
alert('Failed because: ' + message);
}
}
The data sent will then be received on the upload.php file. You should be able to check if the data has been sent by inspecting the files var_dump($_FILES);
As Sletheren mentioned it can also be done using $cordovaFileTransfer.upload();
This is how it works on my side:
First thing: The destinationType should be Camera.DestinationType.FILE_URI,
Second: Set the filename to: filename = imageURI.split('?')[0];
Third: the fileTransfer takes these arguments (it works on my side) :
$cordovaFileTransfer.upload(url, filename, options)
I am working in mean stack application and now I required to make chatting module using the XMPP protocol.
I am new with XMPP,
I have used "node-xmpp-server" and "node-xmpp-client" in node js
and "Strophe.js" in angular js.
My code is as below:
app.js (server side file)
"use strict";
var express = require("express");
var https = require('https');
var http = require("http");
var fs = require('fs');
var app = express();
var xmppClient = require('node-xmpp-client');
var xmppServer = require('node-xmpp-server');
var AES = require("crypto-js/aes");
var CryptoJS = require("crypto-js");
/**
* #description all process variables
*/
require("./config/vars")(app);
var hostName = global.hzConfig.qualifiedHostName;
var config = require("./config/config.js")(app, express);
var friendsArr = [];
var server = null
var startServer = function(done) {
// Sets up the server.
console.log("start server.....");
console.log('xmpp server is listening on port ' + global.hzConfig.xmppServerPort + " on " + process.pid + ' !');
server = new xmppServer.C2S.BOSHServer({
port: global.hzConfig.xmppServerPort,
domain: 'localhost'
})
console.log("server");
console.log(server);
// On connection event. When a client connects.
server.on('connection', function(client) {
// That's the way you add mods to a given server.
// Allows the developer to register the jid against anything they want
console.log('connection');
client.on('register', function(opts, cb) {
console.log('REGISTER')
cb(true)
})
// Allows the developer to authenticate users against anything they want.
client.on('authenticate', function(opts, cb) {
console.log('server:', opts.username, opts.password, 'AUTHENTICATING')
if (opts.password === '') {
console.log('server:', opts.username, 'AUTH OK')
cb(null, opts)
} else {
console.log('server:', opts.username, 'AUTH FAIL')
cb(false)
}
})
client.on('online', function() {
console.log("client");
console.log(client.jid);
console.log('server:', client.jid, 'ONLINE');
friendsArr.push(client.jid);
console.log("friendsArr================>>>>>>>>>>>>>");
console.log(friendsArr);
//client.send(new xmppClient.Message({ type: 'chat' }).c('body').t("Hello there, little client."));
})
// Stanza handling
client.on('stanza', function(stanza) {
console.log(stanza);
console.log('server:', client.jid, 'stanza', stanza.toString())
var body = stanza.getChild('body');
var message = body.getText();
console.log("body===========>>>>>");
console.log(body);
console.log("message===========>>>>>");
console.log(message);
var from = stanza.attrs.from;
stanza.attrs.from = stanza.attrs.to;
stanza.attrs.to = friendsArr[0];
console.log("stanza.attrs");
var sendTo = "laxman#mailinator.com/";
friendsArr.map(function(obj) {
if (obj["user"] === "laxman") {
console.log(obj["_resource"]);
sendTo = sendTo + obj["_resource"];
}
});
//client.send(stanza)
// client.send(stanza)
//console.log("stanza.attrs.from");
//console.log(stanza.attrs.from);
console.log("sendTo++++++++++ ::::: " + sendTo);
var stanza = new xmppClient.Element('message', { to: sendTo, type: 'chat', 'xml:lang': 'ko' }).c('body').t('aaaaaMessage from admin1');
client.send(stanza);
console.log(stanza);
//client.send(new xmppClient.Message({to : sendTo, type: 'chat' }).c('body').t("Hello there, little client."));
})
// On Disconnect event. When a client disconnects
client.on('disconnect', function() {
console.log('server:', client.jid, 'DISCONNECT')
})
})
server.on('listening', function() {})
}
startServer();
message_service.js (clien side file)
(function() {
'use strict';
angular
.module("myApp")
.factory("HzXMPPService", ['$rootScope', '$cookies', '$location', 'HzServices',
function($rootScope, $cookies, $location, HzServices) {
console.log("*****************************************");
return {
OnConnectionStatus: function(conn, obj) {
console.log("conn");
console.log(conn);
console.log("Strophe.Status");
console.log(Strophe.Status);
this.OnConnected(conn);
},
OnConnected: function(conn) {
console.log("OnConnected call");
//Callback fired when availability status of your's or your friends changes.
conn.addHandler(this.OnPresenceStanza, null, "presence");
//callback fired while receiving message
conn.addHandler(this.OnMessageStanza, null, "message");
//callback fired when a friend/authorize request is received
conn.addHandler(this.OnSubscribeStanza, null, "presence", "subscribe");
//callback when your friend/authorize request is responded by another user.
conn.addHandler(this.OnSubscribedStanza, null, "presence", "subscribed");
//send presence to all who have added you to their contact list i.e., send online status to other clients. We are sending "available" status
//conn.send($pres());
},
OnPresenceStanza: function(stanza) {
console.log("OnPresenceStanza call");
var sFrom = $(stanza).attr('from');
console.log("sFrom");
console.log(sFrom);
var sBareJid = Strophe.getBareJidFromJid(sFrom);
console.log("sBareJid");
console.log(sBareJid);
var sTo = $(stanza).attr('to');
console.log("sTo");
console.log(sTo);
var sType = $(stanza).attr('type');
console.log("sType");
console.log(sType);
var sShow = $(stanza).find('show').text();
console.log("sShow");
console.log(sShow);
//OnSubscribeStanza();
//OnSubscribeStanza();
//sendAuthorizeRequest();
sendMessage();
return true;
},
//callback is also fired when other user is typing or paused.
OnMessageStanza: function(stanza) {
console.log("OnMessageStanza call");
console.log(stanza);
var STo = $(stanza).attr('to');
console.log("to");
console.log(STo);
var sType = $(stanza).attr('type');
console.log("sType");
console.log(sType);
var sBareJid = Strophe.getBareJidFromJid(STo);
console.log("sBareJid");
console.log(sBareJid);
var sBody = $(stanza).find('body').text();
console.log("sBody");
console.log(sBody);
if (sBody) {
console.log("A Message Received: " + sBody + " From " + STo);
}
return true;
},
OnSubscribeStanza: function(stanza) {
console.log("OnSubscribeStanza call");
if (stanza.getAttribute("type") == "subscribe") {
var from_id = stanza.getAttribute("from");
console.log("from_id");
console.log(from_id);
//send back authorize request to accept it.
conn.send($pres({ to: from_id, type: "subscribed" }));
}
return true;
},
OnSubscribedStanza: function(stanza) {
console.log("OnSubscribedStanza call");
if (stanza.getAttribute("type") == "subscribed") {
var from_id = stanza.getAttribute("from");
//send back confirm authorize request.
conn.send($pres({ to: from_id, type: "subscribed" }));
}
return true;
},
//make a friend request
sendAuthorizeRequest: function() {
conn.send($pres({ to: "rahul#mailinator.com", type: "subscribe" }));
},
//disconnect from XMPP server
disconnect: function() {
console.log("connected disconnect");
conn.flush();
conn.sync = true;
conn.disconnect();
},
//send a message.
sendMessage: function(conn, msg) {
console.log("Friends call .....");
console.log("conn.jid");
console.log(conn.jid);
//return false;
var message = $msg({ to: "laxman#mailinator.com", from: conn.jid, type: "chat" }).c("body").t(msg);
conn.send(message.tree());
},
onMessage: function(message) {
console.log('service message = ');
console.log(message);
return true;
},
createAccount: function() {
conn = new Strophe.Connection("localhost");
conn.register.connect("localhost", OnConnectionStatus, 60, 1);
}
}
}
]);
}());
For testing, I have used static user for sending a message to Laxman in the server side file.
My main issue is that message can not broadcast to my friends.
I need to return a rejected promise from a js function. I am using angular $q as you can see. But it doesn't work.
In function getDBfileXHR, when the promise getDBfileXHRdeferred is rejected using getDBfileXHRdeferred.reject() I would to pass into the the error case of the function getDBfileXHR and run fallbackToLocalDBfileOrLocalStorageDB(). But it doesn't work.
Is there a syntax error ?
I am a bit new to promises.
Thanks
this.get = function () {
var debugOptionUseLocalDB = 0,
prodata = [],
serverAttempts = 0;
if (debugOptionUseLocalDB) {
return fallbackToLocalDBfileOrLocalStorageDB();
}
if (connectionStatus.f() === 'online') {
console.log("Fetching DB from the server:");
return getDBfileXHR(dbUrl(), serverAttempts)
.then(function () { // success
console.log('-basic XHR request succeeded.');
return dbReadyDeferred.promise;
}, function () { // error
console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
return fallbackToLocalDBfileOrLocalStorageDB();
});
}
}
function getDBfileXHR(url, serverAttempts) {
var getDBfileXHRdeferred = $q.defer(),
request = new XMLHttpRequest();
if (typeof serverAttempts !== "undefined") serverAttempts++;
request.open("GET", url, true); //3rd parameter is sync/async
request.timeout = 2000;
request.onreadystatechange = function () { // Call a function when the state changes.
if ((request.readyState === 4) && (request.status === 200 || request.status === 0)) {
console.log('-we get response '+request.status+' from XHR in getDBfileXHR');
var jsonText = request.responseText.replace("callback(", "").replace(");", "");
if (jsonText === '') {
console.error('-error : request.status = ' + request.status + ', but jsonText is empty for url=' + url);
if (serverAttempts <= 2){
sendErrorEmail("BL: jsonText is empty, trying to reach server another time", 11);
getDBfileXHR(url, serverAttempts);
return;
} else {
sendErrorEmail("BL: jsonText is empty and attempted to reach server more than twice", 14);
var alertPopup = $ionicPopup.alert({
title: 'Error '+"11, jsonText is empty",
template: "Sorry for the inconvenience, a warning email has been sent to the developpers, the app is going to restart.",
buttons: [{
text:'OK',
type: 'button-light'
}]
});
getDBfileXHRdeferred.reject();
}
} else {
}
} else {
console.error('-error, onreadystatechange gives : request.status = ' + request.status);
getDBfileXHRdeferred.reject();
}
};
if (url === "proDB.jsonp") {
console.log("-Asking local proDB.json...");
} else {
console.log("-Sending XMLHttpRequest...");
}
request.send();
return getDBfileXHRdeferred.promise;
}
EDIT:
I rewrote my function using this approach. It seems better and cleaner like this. But now can you help me handle the multiple attempds ?
function getDBfileXHR(url, serverAttempts) {
return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest();
request.open("GET", url, true); request.timeout = 2000;
var rejectdum;
if (url === "proDB.jsonp") {
console.log("-Asking local proDB.json...");
} else {
console.log("-Sending XMLHttpRequest...");
}
request.onload = function () {
if ( (request.readyState === 4) && (request.status === 200 || request.status === 0) ) {
console.log('-we get response '+request.status+' from XHR in getDBfileXHR');
var jsonText = request.responseText.replace("callback(", "").replace(");", "");
if (jsonText === '') {
console.error('-error : request.status = ' + request.status + ', but jsonText is empty for url=' + url);
sendErrorEmail("BL: jsonText is empty, trying to reach server another time", 11);
sendErrorEmail("BL: jsonText is empty and attempted to reach server more than twice", 14);
var alertPopup = $ionicPopup.alert({
title: 'Error '+"11, jsonText is empty",
template: "The surfboard database could not be updated, you won't see the new models in the list, sorry for the inconvenience.",
buttons: [{
text:'OK',
type: 'button-light'
}]
});
console.log('oui on passe rejectdum')
rejectdum = 1;
reject({
status: this.status,
statusText: request.statusText
});
} else {
var parsedJson;
try {
parsedJson = JSON.parse(jsonText);
} catch (e) {
console.warn("Problem when trying to JSON.parse(jsonText) : ");
console.warn(e);
console.warn("parsedJson :");
console.warn(parsedJson);
}
if (parsedJson) {
var prodata = jsonToVarProdata(parsedJson);
console.log('-writing new prodata to localStorage');
console.log('last line of prodata:' + prodata[prodata-1]);
storageService.persist('prodata', prodata);
storageService.store('gotANewDB', 1);
}
resolve(request.response);
dbReadyDeferred.resolve();
}
}
};
request.onerror = function () {
reject({
status: this.status,
statusText: request.statusText
});
};
request.send();
});
}
Is it a clean way to do this to do several attempts :
return getDBfileXHR(dbUrl(), serverAttempts)
.then(function () { // success
console.log('-basic XHR request succeeded.');
return dbReadyDeferred.promise;
})
.catch(function (){
if (typeof serverAttempts !== "undefined") serverAttempts++;
console.log('on passe dans le catch, serverAttempts = ', serverAttempts)
if (serverAttempts < 2) {
return getDBfileXHR(dbUrl(), serverAttempts)
.then(function () { // success
console.log('-basic XHR request succeeded.');
return dbReadyDeferred.promise;
})
.catch(function (){
console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
return fallbackToLocalDBfileOrLocalStorageDB();
})
} else {
console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
return fallbackToLocalDBfileOrLocalStorageDB();
}
})
if you remove the code to retry (twice?) on failure your code would possibly work (haven't looked into that) -
the issue is, the only promise your calling code gets is that of the first attempt. If the first attempt fails, that promise is never resolved or rejected
You need to resolve the promise with the promise returned by getDBfileXHR(url, serverAttempts); - so, something like
if (serverAttempts <= 2){
sendErrorEmail("BL: jsonText is empty, trying to reach server another time", 11);
getDBfileXHRdeferred.resolve(getDBfileXHR(url, serverAttempts));
return;
} else {
Because if promise(1) resolves to a rejected promise(2), the result is that promise(1) rejects with the rejection value of promise(2)
This is how native Promises, and many many Promise/A+ compliant libraries work,
so this should be the case with $.defer if it follows the Promise/A+ spec
We are working on an iOS project in Ionic. We want the cordova screenshot plugin to fire on ionicview enter (when first entering the app), and then use cordova file transfer to send the screenshot.
The below code does not work when first time entering the view. When we leave the view and come back however, it does send a screenshot.
However, the first logAction DOES fire on the first time entering this view while the second logAction does not. When entering this view for the second time, both logActions are fired.
This is the part of the code i am referring to:
$scope.$on('$ionicView.enter', function () {
$scope.logAction({
"Message": "Login screen succesfully entered",
"Succeeded": true,
"transaction": 1,
"Category": "Info",
"Device": 0,
})
$cordovaScreenshot.capture().then(function(filepath){
$scope.logAction({
"Message": filepath,
"Succeeded": true,
"transaction": 1,
"Category": "Info",
"Device": 0,
})
$cordovaScreenshot.send(filepath);
});
});
This is the cordovaScreenshot file
angular.module('testScreenshots.services', [])
.service('$cordovaScreenshot', ['$q',function ($q) {
return {
fileURL: "",
capture: function (filename, extension, quality) {
var randomNumber = Math.random();
console.log("" + randomNumber);
filename = "testPicture" + randomNumber.toString();
extension = extension || 'jpg';
quality = quality || '100';
var defer = $q.defer();
navigator.screenshot.save(function (error, res){
if (error) {
console.error(error);
defer.reject(error);
} else {
console.log('screenshot saved in: ', res.filePath);
this.fileURL = "file://" + res.filePath;
defer.resolve(res.filePath);
console.log("inside the save function: "+this.fileURL);
}
}, extension, quality, filename);
return defer.promise;
},
send: function(filepath){
var win = function (r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
}
var fail = function (error) {
alert("An error has occurred: Code = " + error.code);
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = filepath.substr(filepath.lastIndexOf('/') + 1);
options.mimeType = "multipart/form-data";
options.chunkedMode = false;
options.headers = {
Connection: "close"
};
var ft = new FileTransfer();
ft.upload(filepath, encodeURI("http://192.168.6.165:8080//api/uploadpicture"), win, fail, options);
}
};
}])
The iOS simulator we use on the Mac had this issue. After trying to run it on a device the issue no longer affected us.
This issue thus seems to relate to using the iOS simulator.