Error when removing items from chrome local storage - javascript

I'm trying to get my chrome extension (service worker) to detect when a tab is open to add an object to storage and when a tab is closed to remove the corresponding item from storage. However I'm receiving an error on removal:
Error handling response: TypeError: Error in invocation of storage.remove([string|array] keys, optional function callback): Error at parameter 'keys': Value did not match any choice.
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab)=>{
if (changeInfo.title && tab.status == "complete") {
try {
chrome.storage.local.set({[tabId]:changeInfo})
}
catch(error) {
console.log(error)
}
}
});
chrome.tabs.onRemoved.addListener((tabId, removeInfo)=>{
chrome.storage.local.remove([tabId]) <---- ERROR HERE
})
To make sure the content of the storage I also tried the following to make sure the storage has the object and the key to remove it with:
chrome.tabs.onRemoved.addListener((tabId, removeInfo)=>{
chrome.storage.local.get(null, (storage) => {
console.log(storage)
chrome.storage.local.remove([tabId])
})
})
Been stuck on this for a while so any recommendations are appreciated.

You are giving remove an array of keys ([tabId]), but Storage.removeItem takes a single string representing a storage entry's key.
Try to replace
chrome.storage.local.remove([tabId])
with
chrome.storage.local.remove(tabId)

Related

How to handle DeviceNotRegistered error using expo-server-sdk-node

I built a push notification system on my backend using expo-server-sdk-node. When I want to send notifications, I lookup the expoPushToken in my database. The docs states the following error(s) should be handled:
DeviceNotRegistered: the device cannot receive push notifications
anymore and you should stop sending messages to the corresponding Expo
push token.
However, I am unsure how to handle this error since there are no direct pushTokens available in the error message. See the following example:
[{
status: 'error',
message: '"ExponentPushToken[XXXXXXXXXXXXXXX]" is not a registered push notification recipient',
details: { error: 'DeviceNotRegistered' }
}]
This device should now be removed from my database, but to do that I need the ExponentPushToken[XXXXXXXXXXXXXXX] value. And because the notifications are sent in batches I lose the reference to the user. What is the proper way to do this?
I thought of the following two ways:
1: Just split(") and filter the value, but this depends on the error message.
2: Loop over all my pushTokens, and find where includes(originalValue) in message, but this would mean I'd have to loop over an excessive amount of users every time it fails.
Any recommendations?
I faced the same issue, and here's what I did.
Considering this code
for (let chunk of chunks) {
try {
let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
console.log(ticketChunk);
tickets.push(...ticketChunk);
// If a ticket contains an error code in ticket.details.error
//
} catch (error) {
console.error(error);
}
}
Once I send a batch of notifications (100 most likely).
I loop through the tickets, if ticket.status === 'error' and check for ticket.details.error === 'DeviceNotRegistered' as in the code above.
Since the order of sent notifications is the order in which the response tickets are received.
Using the current index of the tickets loop, I can access the token at the same index in the chunk I sent.
for (let chunk of chunks) {
try {
let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
tickets.push(...ticketChunk);
// If a ticket contains an error code in ticket.details.error
let ticketIndex = 0;
for (let ticket of tickets) {
if (ticket.status === 'error' && ticket.details.error === 'DeviceNotRegistered') {
// Get the expo token from the `chunk` using `ticketIndex`
// Unsubscribe the token or do whatever you want to
}
ticketIndex++;
}
} catch (error) {
console.error(error);
}
}
NB: The code might contain syntax errors, it's the idea I am trying to pass across. I did the same thing with php
It's not documented behaviour (at least I didn't found it in the documentation), but in the ticket error response I can see the expoPushToken in the details object. See the screenshot attached:

How to create a conditional based on a response object, for which the Key values are dependent and avoiding object.key() is Undefined

I'm subscribing to a method in Angular using typescript, which is a simple post Call that returns an entire HTTP Response. I'm wanting to create a simple conditional that checks to see if a certain key exists in the HTTP response. The conditional will work with an object that contains the key, but for an object that doesn't contain the key it throws an undefined.
Is there a way to omit the error or exception thrown and to proceed to the else portion
The keys of the object body are added if the user includes a number, without that it doesn't exist with the PhoneNumber key value
what I've tried / flipped the if and else
!= undefined (vice versa)
== null (vice versa)
this.postMyName(userInfo).subscribe(
(result:Response) => {
if (result['body']['user'].hasOwnProperty(['PhoneNumber'])) {
console.log("User has included a phoneNumber");
} else {
console.log("User has Not included a phoneNumber");
}
},error ...)
You can also try this solution maybe it will work
this.postMyName(userInfo).subscribe(
(result:Response) => {
if ('PhoneNumber' in result['body']['user'])) {
console.log("User has included a phoneNumber");
} else {
console.log("User has Not included a phoneNumber");
}
},error ...)

Uncaught SyntaxError: Unexpected token u in JSON at position 0

Only at the checkout and on individual product pages I am getting the following error in the console log:
VM35594:1 Uncaught SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse (<anonymous>)
at run (layout.min.js:9)
at app.min.js:1
at main.min.js:2
at Object.execCb (require.min.js:112)
at Module.check (require.min.js:56)
at Module.<anonymous> (require.min.js:72)
at require.min.js:11
at require.min.js:74
at each (require.min.js:3)
I am using a one page checkout extension, but when I disable that the error still shows. I thought it might had something to do with the reviews on the product page (as I moved the reviews out of the tabs), but undoing that change didn't fix the error on the product pages.
Try this in the console:
JSON.parse(undefined)
Here is what you will get:
Uncaught SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse (<anonymous>)
at <anonymous>:1:6
In other words, your app is attempting to parse undefined, which is not valid JSON.
There are two common causes for this. The first is that you may be referencing a non-existent property (or even a non-existent variable if not in strict mode).
window.foobar = '{"some":"data"}';
JSON.parse(window.foobarn) // oops, misspelled!
The second common cause is failure to receive the JSON in the first place, which could be caused by client side scripts that ignore errors and send a request when they shouldn't.
Make sure both your server-side and client-side scripts are running in strict mode and lint them using ESLint. This will give you pretty good confidence that there are no typos.
As #Seth Holladay #MinusFour commented, you are parsing an undefined variable.
Try adding an if condition before doing the parse.
if (typeof test1 !== 'undefined') {
test2 = JSON.parse(test1);
}
Note: This is just a check for undefined case. Any other parsing issues still need to be handled.
localStorage.clear()
That'll clear the stored data. Then refresh and things should start to work.
Your app is attempting to parse the undefined JSON web token. Such malfunction may occur due to the wrong usage of the local storage. Try to clear your local storage.
Example for Google Chrome:
F12
Application
Local Storage
Clear All
For me, that happened because I had an empty component in my page -
<script type="text/x-magento-init">
{
".page.messages": {
"Magento_Ui/js/core/app": []
}
}
Deleting this piece of code resolved the issue.
This is due to the interfering messages that come on to the page. There are multiple frames on the page which communicate with the page using window message event and object. few of them can be third party services like cookieq for managing cookies, or may be cartwire an e-com integration service.
You need to handle the onmessage event to check from where the messages are coming, and then parse the JSON accordingly.
I faced a similar problem, where one of the integration was passing a JSON object and other was passing a string starting with u
If you get Uncaught SyntaxError: Unexpected token u in JSON at position 0 then you could do the following quick checks:
jsObj = JSON.parse(data)
data - check the data is undefined or not
data - check the data is a valid JSON string or not
data - check the data is corrupted by unwanted whitespace or not
data = data.trim(); // remove the unwanted whitespace
jsObj = JSON.parse(data);
data - check the received data uses the correct encoding format('utf8', 'utf16le', 'ucs2') or not
fs.readFile(file, 'utf8', function(err, data) { ... });
fs.readFile(file, 'utf16le', function(err, data) { ... }); // le - little endian
fs.readFile(file, 'ucs2', function(err, data) { ... }); // kind of 'utf16le'
I had this issue for 2 days, let me show you how I fixed it.
This was how the code looked when I was getting the error:
request.onload = function() {
// This is where we begin accessing the Json
let data = JSON.parse(this.response);
console.log(data)
}
This is what I changed to get the result I wanted:
request.onload = function() {
// This is where we begin accessing the Json
let data = JSON.parse(this.responseText);
console.log(data)
}
So all I really did was change
this.response to this.responseText.

Querying for local storage entry without throwing errors

Working on a chrome extension. I am using the following to save some data to my local storage:
chrome.storage.local.set({ [variablyNamedEntry]: someObjectToBeSaved });
Elsewhere in my code I want to query if the entry exists and if it does, I will want to local some variable "myVar" with the object.
If the entry exists, this code works to achieve my goals:
chrome.storage.local.get(null, function(result){
myVar = result[variablyNamedEntry];
}
But if no entry exists for "variablyNamedEntry" it throws an error. I could manage this error with a try/catch sequence. But that can't be the best approach, given that I know that it will not find the entry a very large percentage of the time.
How can I achieve my goal?
Update:
I tried using:
chrome.storage.local.get([variablyNamedEntry], function(result){
if (result != undefined)
myVar = result[variablyNamedEntry];
}
But I still get the following error if the entry does not exist:
extensions::uncaught_exception_handler:8 Error in response to storage.get: TypeError: Cannot read property 'someProperty' of undefined
Please be aware the items parameter for the callback of chrome.storage.local.get is always an object and would never be undefined.
Assuming you have a key-value in which key is 'Sample-Key', you could use the following code
chrome.storage.local.get(null, function(result){
if(typeof result['Sample-Key'] !== 'undefined') {
console.log(result['Sample-Key']);
}
});
Or
chrome.storage.local.get('Sample-Key', function(result){
if(typeof result['Sample-Key'] !== 'undefined') {
console.log(result['Sample-Key']);
}
});

chrome.storage not working as expected

I am trying to save a list of dictionary objects in the chrome storage. But the following code seems to not work as expected.
When the extension loads for the first time and there is no goal object in the storage, runtime.lasterror object should be set and the code in that part should get executed. But it isn't.
When I uncomment the chrome.storage.sync.set line and save the object and the next time I call the function expecting it to save a list, it doesn't. It does not give any of the alert boxes.
function isPgUrl(pg_url,gl_name) {
if(pg_url && gl_name) {
dic_url={
"name":gl_name,
"pg_url":pg_url
}
//chrome.storage.sync.set({"goal":[dic_url]});
chrome.storage.sync.get(["goal"], function(data) {
if(chrome.runtime.lastError) {
chrome.storage.sync.set({"goal":[dic_url]},function() {
alert("blah");
});
alert("here");
return;
}
var list=data.goal;
list.append(dic_url);
alert(list);
chrome.storage.sync.set({"goal":list},function() {
alert("lalala");
return;
});
});
}
}
You'll never get chrome.runtime.lastError set for missing data. It's not an exception - you just get undefined value. So your check should be:
if(!data.goal) { ... }
or
if(typeof data.goal === "undefined") { ... }
If you uncomment that line, you need to be aware that chrome.storage is asynchronous: the data is not in storage until the callback of .set(). So your .get() that is executed immediately after calling .set() may get a snapshot of the older view of the storage - making your code fail at list.append(dic_url);
Not that Array.prototype.append exists in the first place. You should be using .push().
Chrome Storage has a more efficient way of setting a default-if-not-in-storage value, by using an Object as a query:
chrome.storage.sync.get({key: "defaultValue"}, function(data) {
// data.key will be the stored value, or "defaultValue" if not in storage
});
So, if I understand the purpose of your code correctly (append dic_url to goal in storage), this will do it:
// Makes more sense to default to empty list
chrome.storage.sync.get({goal: []}, function(data) {
var list = data.goal;
list.push(dic_url);
chrome.storage.sync.set({goal: list}, function() {
// Stoarge updated, dic_url appended to goal
});
// Storage is not yet updated - set() is async
});
// Storage is not yet updated - get()/set() are async

Categories

Resources