Is there any way to keep LG WebOS service alive? - javascript

I’m trying to create a JS service on WebOS 3.0 followed the official documentation.
I can send data between JS service and my application, but sometimes the JS service does not respond to the request if it’s idled for like 20 seconds. I’ve also tried to increase the timeout per this. Unfortunately, it does not seemed to be working.
Here’s my code
Application Side
const request = webOS.service.request('luna://com.myapp.service', {
method : 'fetch',
parameters : { url, method, headers, body },
onFailure : (err) => {
reject(err)
},
onSuccess : (s) => {
console.log('request success', s)
},
onComplete : (resp) => {
const isSuccess = resp.data.status >= 200 && resp.data.status < 400
var payload = {
json : () => Promise.resolve(JSON.parse(resp.data.body)),
ok : isSuccess,
headers : resp.data.headers,
status : resp.data.status,
error : isSuccess
? null
: resp.data.body
}
resolve(payload)
}
})
})
Service Side
var Service = require('webos-service')
var service = new Service('com.myapp.service')
service.register('fetch', function(message) {
var payload = message.payload
if(!payload) {
message.respond({
returnValue : true,
error : 'Message does not have a `payload`'
})
return
}
var url = payload.url,
headers = payload.headers,
method = payload.method,
body = payload.body
var request = http.request({
method : method,
hostname : URL.parse(url).hostname,
path : URL.parse(url).path,
headers : headers,
}, function(res) {
var data = ''
res.on('data', function(chunk) { data+=chunk })
res.on('end', function() {
message.respond({
returnValue : true,
data : {
status : res.statusCode,
statusText : res.statusMessage,
headers : res.headers,
body : data,
}
})
})
})
request.on('error', function(err) {
console.log(err)
message.respond({
returnValue : true,
error : err
})
})
request.end()
})

I recently wrote a JavaScript application for LG Smart-TVs and would highly recommend using socket.io for all communication between client and server.
It's a bit tricky getting it to work initially, but works flawlessly.
Here's how the connection looks ...
var socket = io("http://10.27.101.95");
idUser = getCookie("idUser"); // Retrieved from device and set to cookie.
// ┌────────────────────────────────────────────────────────────────┐
// │ Socket.io: Connect/Emit │
socket.on('connect', function() {
socket.emit("addUser", {
"idUser": idUser
});
reconnectHideData = false;
});
// Hide data if server cannot be reached.
var reconnectCount = 0;
var reconnectHideData = false;
socket.on('reconnect_error', function() {
if (reconnectCount < 10 && reconnectHideData == false) {
// console.log( '---=== Reconnect attempt: ' + reconnectCount + ' ===---' );
setTimeout(function(){
reconnectCount++;
}, 3000);
}
if (reconnectCount == 10 && reconnectHideData == false) {
// console.log( '-----===== Cleared Data =====-----' );
$('.section ').addClass(' u-hide ');
$('.greeting').addClass(' u-hide ');
reconnectHideData = true;
reconnectCount = 0;
}
else {
return;
}
});
// Necessary to trigger event to be emitted server side.
setInterval(function(){
socket.emit("reqData");
}, 5000);
// └────────────────────────────────────────────────────────────────┘
After that, it's all a matter of processing and formatting the returned data.

Related

navigator.serviceWorker.ready promise not getting resolved on push notifications on Production... Actually the code is working on development

I want to run the function configurePushSub down bellow whenever an event is fired on a page for my create-react-app... It is working everything fine on development mode, however when I hosted my app on Netlify the promise navigator.serviceWorker.ready is not getting resolved as I cannot see the message in the console navigator has loaded... I have already tried everything possible to get that working but everything unsuccessfull
function configurePushSub() {
if (!('serviceWorker' in navigator)) {
return;
}
let hasUnsubscribed;
var reg;
console.log(
'running',
navigator.serviceWorker,
navigator.serviceWorker.ready
);
navigator.serviceWorker.ready
.then(function (swreg) {
console.log(swreg, 'navigator has loaded');
reg = swreg;
return swreg.pushManager.getSubscription();
})
.then((sub) => {
if (!!sub) {
return sub.unsubscribe().then(function (s) {
hasUnsubscribed = true;
return navigator.serviceWorker.ready;
});
}
return navigator.serviceWorker.ready;
})
.then(function (sub) {
var vapidPublicKey =
'BOChVD1tKTc0Of3c-0JplT1y5FPOm6oijP_4stWBXwoQe6xI4GGt6cnpdu4JLwt_Znj23bj_hku8OSois1y9fLE';
var convertedVapidPublicKey = urlBase64ToUint8Array(vapidPublicKey);
return reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: convertedVapidPublicKey,
});
})
.then(async function (newSub) {
let key;
let authSecret;
let endPoint;
if (newSub) {
const rawKey = newSub.getKey ? newSub.getKey('p256dh') : '';
key = rawKey
? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey)))
: '';
var rawAuthSecret = newSub.getKey ? newSub.getKey('auth') : '';
authSecret = rawAuthSecret
? btoa(
String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))
)
: '';
endPoint = newSub.endpoint;
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
};
const gpuTier = await getGPUTier();
const info = getOperatingSystemName(this);
console.log(info);
if (hasUnsubscribed) {
await axios.put(
`${Config.SERVER_ADDRESS}/api/pushNotifications/id`,
{
endpoint: endPoint,
key,
auth: authSecret,
gpu: gpuTier.gpu,
operating_system: `${info.os} ${info.osVersion}`,
device: info.mobile ? 'mobile' : 'desktop',
browser: `${info.browser} ${info.browserMajorVersion}`,
operating_system_architecture: info.arch,
},
config
);
} else {
await axios.post(
`${Config.SERVER_ADDRESS}/api/pushNotifications/`,
{
endpoint: endPoint,
key,
auth: authSecret,
gpu: gpuTier.gpu,
operating_system: `${info.os} ${info.osVersion}`,
device: info.mobile ? 'mobile' : 'desktop',
browser: `${info.browser} ${info.browserMajorVersion}`,
operating_system_architecture: info.arch,
},
config
);
}
}
})
.then(function (res) {
displayConfirmNotification();
})
.catch(function (err) {
console.log(err);
});
}
I have just managed to get that working...
It is just that I haven't registered the service worker for the production mode...
When I was on development I have written the following code, but then I moved to the production and I have forgotten about it.
navigator.serviceWorker.register(`/sw.js`)

Postman post request works but ajax post does not. Have checked client side js over and over

first question ever on stackoverflow and boy do I need an answer. My problem is that I have an endpoint to create an item, and it works when I send a POST request with Postman. I'm using node and express:
router.post("/", jwtAuth, (req, res) => {
console.log(req.body);
const requiredFields = ["date", "time", "task", "notes"];
requiredFields.forEach(field => {
if (!(field in req.body)) {
const message = `Missing \`${field}\` in request body`;
console.error(message);
return res.status(400).send(message);
}
});
Task.create({
userId: req.user.id,
date: req.body.date,
time: req.body.time,
task: req.body.task,
notes: req.body.notes
})
.then(task => res.status(201).json(task.serialize()))
.catch(err => {
console.error(err);
res.status(500).json({ message: "Internal server error" });
});
});
That endpoint works when I send with Postman and the req body logged with the right values.
But when I send my ajax request, my server code logs the req.body as an empty object ('{}'). Because Postman works I believe the problem is with my client side javascript but I just cannot find the problem. I and others have looked over it a million times but just can't find the problem. Here is my client side javascript:
//User submits a new task after timer has run
function handleTaskSubmit() {
$(".submit-task").click(event => {
console.log("test");
const date = $(".new-task-date").text();
const taskTime = $(".new-task-time").text();
const task = $(".popup-title").text();
const notes = $("#task-notes").val();
$(".task-notes-form").submit(event => {
event.preventDefault();
postNewTask(date, taskTime, task, notes);
});
});
}
function postNewTask(date, taskTime, task, notes) {
const data = JSON.stringify({
date: date,
time: taskTime,
task: task,
notes: notes
});
//Here I log all the data. The data object and all its key are defined
console.log(data);
console.log(date);
console.log(taskTime);
console.log(task);
console.log(notes);
const token = localStorage.getItem("token");
const settings = {
url: "http://localhost:8080/tasks",
type: "POST",
dataType: "json",
data: data,
contentType: "application/json, charset=utf-8",
headers: {
Authorization: `Bearer ${token}`
},
success: function() {
console.log("Now we are cooking with gas");
},
error: function(err) {
console.log(err);
}
};
$.ajax(settings);
}
handleTaskSubmit();
What I would do:
Change header 'application/json' to 'application/x-www-form-urlencoded' since official docs have no info on former one.
Stop using $.ajax and get comfortable with XHR requests, since jquery from CDN is sometimes a mess when CDN get's laggy and XHR is a native implement and available immediately. Yes it's a code mess, but you always know that it is not the inner library logic thing, but your own problem. You blindly use library, that conceals XHR inside and you do not know how to ask the right question "XHR post method docs" because you are not yet comfortable with basic technology underneath.
Save this and import the variable
var httpClient = {
get: function( url, data, callback ) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
var readyState = xhr.readyState;
if (readyState == 4) {
callback(xhr);
}
};
var queryString = '';
if (typeof data === 'object') {
for (var propertyName in data) {
queryString += (queryString.length === 0 ? '' : '&') + propertyName + '=' + encodeURIComponent(data[propertyName]);
}
}
if (queryString.length !== 0) {
url += (url.indexOf('?') === -1 ? '?' : '&') + queryString;
}
xhr.open('GET', url, true);
xhr.withCredentials = true;
xhr.send(null);
},
post: function(url, data, callback ) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
var readyState = xhr.readyState;
if (readyState == 4) {
callback(xhr);
}
};
var queryString='';
if (typeof data === 'object') {
for (var propertyName in data) {
queryString += (queryString.length === 0 ? '' : '&') + propertyName + '=' + encodeURIComponent(data[propertyName]);
}
} else {
queryString=data
}
xhr.open('POST', url, true);
xhr.withCredentials = true;
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(queryString);
}
};
usage is as simple as jquery: httpClient.post(Url, data, (xhr) => {})
Check if you have body parser set-up in app.js
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // get information from html forms
app.use(bodyParser.urlencoded({ extended: true })); // get information from html forms
if body parser is set-up try changing header to 'multipart/form-data' or
'text/plain'.
For just the sake check req.query
Cheers! :)

passing error message from service to controller in angularjs

Controller.js
var vm = this;
vm.admin = {};
vm.add = function () {
API.addAdmin(token, vm.admin)
.then(function (resp) {
vm.hideForm = true;
vm.showButton = true;
Notify.green(resp);
}, function (resp) {
Notify.red(resp);
});
};
API.js
function addAdmin(token, dataObj) {
return Constant.getApiUrl()
.then(function (url) {
$http({
method: 'POST',
url: url + '/client/admin',
headers: {
'Token': token
},
data: dataObj
}).then(handleResp);
function handleResp(resp) {
var responseStatus = (resp.status >= 200 && resp.status < 300) ? 'good' : 'bad';
if (responseStatus === 'good') {
console.log("Success" + resp);
return resp;
} else {
console.log("Failed" + resp);
return resp;
}
}
})
}
If I get a success response in API then i need to connect it to success function in my controller and if i get error message in my API, then i need it to connect it to error function in my controller.How should I evaluate the response status from my API(is either success or error).
I don't want to pass successfn, errorfn from my controller to API(only if there's no alternative).
I need to get the response data from API to controller to show it in Notify message.
Thank You!
In service (assign response values in "originalData"):
angular.module('appname').service('myserviceName', function(yourExistingService){
this.myFunction= function(originalData) {
//for next line to work return promise from your addAdmin method.
var promise = yourExistingService.getResponseFromURL(originalData);
return promise;
}
});
And in your controller :
var promise = myserviceName.myFunction($scope.originalData);
promise.$promise.then(function() {
console.log($scope.originalData);
});
And then you can check you "originalData" and write code according to your need.For more detail you can have a look on this http://andyshora.com/promises-angularjs-explained-as-cartoon.html.

Web Push Service Ocasionally Bugs

Not sure what I'm doing wrong with my service worker implementation.
Ideally, I'm facing problems with either "The Website has been refreshed in the background" with this one.
I didn't have this problem before with the code, but once the Push Notification subscribers count got to around 600 it started to cause issues with every single one of them.
var init = { method: 'GET',
headers: {
"Content-Type" : "application/javascript"
},
mode: 'cors',
cache: 'no-cache'
};
var worker = self;
var the_endpoint = '';
fetch(the_endpoint, init ).then(function(response) {
return response.json();
}).then(function(data){
worker.addEventListener('push', function(event) {
event.waitUntil(
worker.registration.showNotification(data.title, {
body : data.body,
icon : data.icon,
requireInteraction : true
})
);
});
if( data.link != '' ) {
worker.addEventListener('notificationclick', function(event) {
event.notification.close();
var url = data.link;
event.waitUntil(
clients.matchAll({
type: 'window'
})
.then(function(windowClients) {
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
if (client.url === url && 'focus' in client) {
return client.focus();
}
}
if (clients.openWindow) {
return clients.openWindow(url);
}
})
);
});
}
});
Attempt 2 that doesn't have the background refresh issue, but doesn't always work.
var init = { method: 'GET',
headers: {
"Content-Type" : "application/javascript"
},
mode: 'cors',
cache: 'no-cache'
};
var worker = self;
var the_endpoint = '';
self.addEventListener('push', function(event) {
event.waitUntil(
fetch(the_endpoint, init).then(function (response) {
return response.json().then(function (data) {
var response = self.registration.showNotification(data.title, {
body: data.body,
icon: data.icon,
requireInteraction: true
});
if (data.link != '') {
worker.addEventListener('notificationclick', function (event) {
event.notification.close();
var url = data.link;
event.waitUntil(
clients.matchAll({
type: 'window'
}).then(function (windowClients) {
for (var i = 0; i < windowClients.length; i++) {
var client = windowClients[i];
if (client.url === url && 'focus' in client) {
return client.focus();
}
}
if (clients.openWindow) {
return clients.openWindow(url);
}
})
);
});
}
return response;
});
})
);
});
The reason this often occurs is the promise returned to event.waitUntil() didn't resolve with a notification being shown.
An example that might show the default "The Website has been refreshed in the background" notification:
function handlePush() {
// BAD: The fetch's promise isn't returned
fetch('/some/api')
.then(function(response) {
return response.json();
})
.then(function(data) {
// BAD: the showNotification promise isn't returned
showNotification(data.title, {body: data.body});
});
}
self.addEventListener(function(event) {
event.waitUntil(handlePush());
});
Instead you could should write this as:
function handlePush() {
// GOOD
return fetch('/some/api')
.then(function(response) {
return response.json();
})
.then(function(data) {
// GOOD
return showNotification(data.title, {body: data.body});
});
}
self.addEventListener(function(event) {
const myNotificationPromise = handlePush();
event.waitUntil(myNotificationPromise);
});
The reason this is all important is that browsers wait for the promise passed into event.waitUntil to resolve / finish so they know the service worker needs to be kept alive and running.
When the promise resolves for a push event, chrome will check that a notification has been shown and it falls into a race condition / specific circumstance as to whether Chrome shows this notification or not. Best bet is to ensure you have a correct promise chain.
I put some extra notes on promises on this post (See: 'Side Quest: Promises' https://gauntface.com/blog/2016/05/01/push-debugging-analytics)

Google Apps Script Drive Error

This is my first post on SO so I hope I'm doing this correctly. I have a Google Apps Script that is being used with as a web hook to create an integration between two services: YouCanBook.Me and Taleo. The script was published as a web app with the "Anyone, even anonymous" access and was working for weeks. Recently (as of 2/3/14 I believe) it stopped working and now navigating to the public URL results in the following error message:
Google Drive encountered an error. If reloading the page doesn't help, please report the error.
To learn more about Google Drive, please visit our help center.
We're sorry for the inconvenience. Thanks for your help!
- The Google Drive Team
Here is the code for the entire script:
function doGet(request) {
try {
//Get token data from URL parameters
var candidateID = request.parameter.candID;
var requisitionID = request.parameter.reqID;
var interviewType = request.parameter.intType;
var requestType = request.parameter.request;
}
catch(e) {
Logger.log('Unable to capture required parameters. Error message: ' + e);
return;
}
//Get authToken by passing in credentials
var authToken = taleoLogin();
//Get candidate application ID
var candidateApplicationID = getCandidateApplicationID(authToken, candidateID, requisitionID);
//Make PUT request to change candidate's status
taleoSubmit(authToken, candidateID, requisitionID, candidateApplicationID, interviewType, requestType);
//Logout
taleoLogout(authToken);
}
function getCandidateApplicationID(authToken, candidateID, requisitionID) {
//Build API call
var loginURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication?candidateId=' + candidateID + '&requisitionId=' + requisitionID;
var loginOptions = {
'method' : 'get',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8'
};
//Make API call
try {
var loginResponse = UrlFetchApp.fetch(loginURL, loginOptions);
if (loginResponse.getResponseCode() == 200) {
Logger.log('Logged in!');
}
else {
Logger.log('Error logging in: ' + loginResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not log in: ' + e);
}
//Return candidate application ID
return candidateApplicationID = JSON.parse(loginResponse).response.candtoreqs[0].candidateapplication.id.toFixed(0);
}
//-----------------------------------//
// Log into Taleo via the REST API //
//-----------------------------------//
function taleoLogin() {
//Build API call
var loginURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/login?orgCode=[companyCode]&userName=[username]&password=[password]';
var loginOptions = {
'method' : 'post',
'contentType' : 'application/json'
};
//Make API call
try {
var loginResponse = UrlFetchApp.fetch(loginURL, loginOptions);
if (loginResponse.getResponseCode() == 200) {
Logger.log('Logged in!');
}
else {
Logger.log('Error logging in: ' + loginResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not log in: ' + e);
}
//Return full authToken key
return authToken = 'authToken=' + JSON.parse(loginResponse).response.authToken;
}
//-------------------------------------//
// Log out of Taleo via the REST API //
//-------------------------------------//
function taleoLogout(authToken) {
//Build API call
var logoutURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/logout';
var logoutOptions = {
'method' : 'post',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8'
};
//Make API call
try {
var logoutResponse = UrlFetchApp.fetch(logoutURL, logoutOptions);
if (logoutResponse.getResponseCode() == 200) {
Logger.log('Logged out!');
}
else {
Logger.log('Error logging out: ' + logoutResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not log out: ' + e);
}
}
//-----------------------------------------//
// Submit data to Taleo via the REST API //
//-----------------------------------------//
function taleoSubmit(authToken, candID, reqID, appID, intType, requestType) {
//If phone interview and initial booking
if(intType == 'phone' && requestType == 'booking') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5033 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
else if(intType == 'final' && requestType == 'booking') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5048 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
else if(intType == 'phone' && requestType == 'cancel') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5032 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
else if(intType == 'final' && requestType == 'cancel') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5047 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
//Make API call
try {
var submitResponse = UrlFetchApp.fetch(submitURL, submitOptions);
if (submitResponse.getResponseCode() == 200) {
Logger.log('Results submitted!');
}
else {
Logger.log('Error submitting results: ' + submitResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not submit results: ' + e);
}
}

Categories

Resources