Chrome Extension: How to get object from DB when searching by value? - javascript

Im trying to create a chrome extension, and have encountered an annoying problem. I have this function, where I add an object to my indexedDB if the urlKeyValue of that object, does not already exist in the database.
If the urlKeyValue does exist in the DB, i want to get the object in the DB that contains that value. This is where my problem begins. On line 184 - 188, i try to get the object by searching by the `urlKeyValue, but when I try to print the object, i get undefined.
Question: How to get an object from IndexedDB by a value?
This is how my objects are structured:
{
message: "insert",
payload: [
{
urlKeyValue: "",
url: {
[userId]: {
[time]: {
msg: form_data.get("message"),
},
},
},
},
],
}
My Function where it all happens:
function insert_records(records, when) {
if (db) {
const insert_transaction = db.transaction(["roster2"], "readwrite");
const objectStore = insert_transaction.objectStore("roster2");
return new Promise((resolve, reject) => {
insert_transaction.oncomplete = function () {
console.log("ALL INSERT TRANSACTIONS COMPLETE.");
resolve(true);
};
insert_transaction.onerror = function () {
console.log("PROBLEM INSERTING RECORDS.");
resolve(false);
};
records.forEach((person) => {
// the "when" varieable isnt important, just disregard it
if (when != "init") {
const index = objectStore.index("urlKeyValue");
let search = index.get(person.urlKeyValue);
search.onsuccess = function (event) {
if (search.result === undefined) {
// no record with that key
let request = objectStore.add(person);
request.onsuccess = function () {
console.log("Added: ", person);
};
}
else {
const request2 = objectStore.get(person.urlKeyValue);
request2.onsuccess = function (event) {
console.log("--------" + event.target.result);
};
}
};
} else {
// this else statement isnt really important for this question
let request = objectStore.add(person);
request.onsuccess = function () {
console.log("Added: ", person);
//self.location.href;
};
}
});
});
}
}
EDIT:
This is an example of an object I store:
let roster = [
{
urlKeyValue: "https://www.youtube.com/",
"https://www.youtube.com/": {
1: {
20: {
msg: "this is some init data",
},
},
},
},
];

Related

Why do I get this error while trying to insert data to SQL Server with NodeJS and Tedious?

Working in a NodeJS that saves data to a SQL Server Database, it must save data from an array of objects but when I run it I get this error, just looked here and documentation but I don't really understand how to fix it, any help is welcomed. This is the error:
PS D:\Users\****\****\****\****\****> node appb.js
Successful connection
events.js:135
throw new ERR_INVALID_ARG_TYPE('listener', 'Function', listener);
^
TypeError [ERR_INVALID_ARG_TYPE]: The "listener" argument must be of type function. Received type string ('row')
And this is my app.js:
Connection:
var Connection = require("tedious").Connection;
var lstValid = [];
var config = {
server: "SERVER",
authentication: {
type: "default",
options: {
userName: "USERNAME",
password: "PASSWORD",
},
},
options: {
encrypt: true,
database: "DATABASE",
instanceName: 'INSTANCENAME'
},
};
var connection = new Connection(config);
connection.on("connect", function (err) {
console.log("Successful connection");
executeStatement1();
});
connection.connect();
and here's where I insert data:
async function calcWeather() {
const info = await fetch("../json/data.json")
.then(function (response) {
return response.json();
});
for (var i in info) {
const _idOficina = info[i][0].IdOficina;
const lat = info[i][0].latjson;
const long = info[i][0].lonjson;
const base = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${api_key}&units=metric&lang=sp`;
fetch(base)
.then((responses) => {
return responses.json();
})
.then((data) => {
var myObject = {
Id_Oficina: _idOficina,
// Other thins in myObject
};
// validation and saving data to array
if (myObject.Temperatura < 99) {
lstValid.push(myObject);
}
});
}
}
var Request = require("tedious").Request;
var TYPES = require("tedious").TYPES;
function executeStatement1() {
calcWeather();
for (var m = 0; m <= lstValid.length; m++) {
Request = new Request(
"INSERT INTO TB_BI_CSL_RegistroTemperaturaXidOdicina (IdOficina, Humedad, Nubes, Sensacion, Temperatura, Descripcion) VALUES (#IdOficina, #Humedad, #Nubes, #Sensacion, #Temperatura)",
function (err) {
if (err) {
console.log("Couldn't insert data: " + err);
}
}
);
Request.addParameter("IdOficina", TYPES.SmallInt, lstValid[m]);
// Other things inserted
Request.on('requestCompleted',"row", function (columns) {
columns.forEach(function (column) {
if (column.value === null) {
console.log("NULL");
} else {
console.log("Product id of inserted item is " + column.value);
}
});
});
Request.on("requestCompleted", function (rowCount, more) {
connection.close();
});
connection.execSql(Request);
}
}
Seems that there are too many parameters to the request.on(...) method, i.e.:
Request.on('requestCompleted',"row", function (columns)
Should probably be:
Request.on("row", function (columns)
The error says the JavaScript function received arguments that were different than expected:
...ERR_INVALID_ARG_TYPE('listener', 'Function', listener);
If it has never worked, the function was likely mistyped. (If it has worked, it could be bad data coming in)
The next message gives a further information:
"...The "listener" argument must be of type function. Received type string ('row')"
A JavaScript function to do work was expected, but it received a simple string 'row' instead.
events.js:135
This means the error happened in the file 'events.js' on or before line 135.
The TediusJs API Request Docs, provides a reference example:
request.on('row', function (columns) { /* code to process rows */ });
In your example we find:
Request.on('requestCompleted',"row", function (columns) {
Most likely it should be:
Request.on("row", function (columns) {
Although I am not positive which line in your example is line 135.

IndexedDB is not showing data in debugger but showing in console

I am doing a ajax call and store the response data into indexedDB. The response is an array of strings. After checking many questions and suggestions, i have followed the answer of #buley and did like this below :
$(document).ready(function () {
var db_name = 'mobileClaimsDb',
store_name = 'claims';
$.ajax({
url: 'index.cfm?action=main.appcache',
type: 'post',
cache:true,
success: function (data) {
var request,
upgrade = false,
doTx = function (db, entry) {
addData(db, entry, function () {
getData(db);
});
},
getData = function (db) {
db.transaction([store_name], "readonly").objectStore(store_name).openCursor(IDBKeyRange.lowerBound(0)).onsuccess = function (event) {
var cursor = event.target.result;
if (null !== cursor) {
console.log("entry", cursor.value);
cursor.continue();
}
};
},
addData = function (db, entry, finished) {
console.log('adding', entry);
var tx = db.transaction([store_name], "readwrite"),
claims = [];
tx.addEventListener('complete', function (e) {
finished();
});
$.each(claims, function (key, value) {
tx.objectStore(store_name).add(value);
});
};
request = window.indexedDB.open(db_name);
request.oncomplete = function (event) {
if (upgrade) {
doTx(request.result, data);
}
};
request.onsuccess = function (event) {
if (!upgrade) {
doTx(request.result, data);
}
};
request.onupgradeneeded = function (event) {
var db = event.target.result;
db.createObjectStore('claims', {
keyPath: null,
autoIncrement: true
});
}
}
});
});
It is creating the db and store too but data is not showing while opening the store.But, it is showing the data in console with key/value pair. I am not understand why it is not showing.
It is showing like this.
In console, it is populating properly.
What changes i need to do to show the key and value pair in store.

How to modify object in complex array?

I have such a data structure:
data: [
{
current: true,
id: "3d6266501370d",
name: "Option",
items: [
{
hidden: false,
id: "ed716c12bf8f3",
data: "ffff",
}
],
selected_queries:[
{
id: 67896,
data: "ff",
}
]
},
]
and I need to edit just hidden filed of every object, other values I need to keep as it is. I created such a code:
export const editField = (id, status) => {
return new Promise((res) => {
const data = getData();
const newData = data.map(dataItem => {
if (dataItem.current) {
const newDataItem = dataItem.items.map(item => {
if (item.id === id) {
return Object.assign({}, item, {
...item,
hidden: status,
});
} else {
return item;
}
})
return newDataItem;
} else {
return dataItem;
}
})
res(newData);
});
}
but I get new object whch has null. Can somebody help me with this?
When you are calling data = getData() (per Marks's comment) it is assigning data = null until getData() returns. Only then is it getting updated. So newData = data.map... is being run on nothing. You could assign a callback on getData:
function getData(cb){
data = get the data..
cb(data)
}
//Then use it like:
const data = getData(function(data){
newData = data.map...
});
You could transform getData() in a Promise too, something like:
var promiseData = new Promise(function(resolve, reject) {
resolve(getData());
});
promiseData.then(function(data) {
// THE REST OF YOUR CODE USING "data"
}).catch(function(error){
console.error(error);
});
Then you'll be sure that you got the data you needed.

How can I convert the following JavaScript Promise into regular asychronous code?

Hi I'm working with the following code snippet:
imaps.connect(config).then(function (connection) {
connection.openBox('INBOX').then(function () {
// Fetch emails from the last 24h
var delay = 24 * 3600 * 1000;
var yesterday = new Date();
yesterday.setTime(Date.now() - delay);
yesterday = yesterday.toISOString();
var searchCriteria = ['UNSEEN', ['SINCE', yesterday]];
var fetchOptions = { bodies: ['HEADER.FIELDS (FROM TO SUBJECT DATE)'], struct: true };
// retrieve only the headers of the messages
return connection.search(searchCriteria, fetchOptions);
}).then(function (messages) {
var attachments = [];
messages.forEach(function (message) {
var parts = imaps.getParts(message.attributes.struct);
attachments = attachments.concat(parts.filter(function (part) {
return part.disposition && part.disposition.type.toUpperCase() === 'ATTACHMENT';
}).map(function (part) {
// retrieve the attachments only of the messages with attachments
return connection.getPartData(message, part)
.then(function (partData) {
return {
filename: part.disposition.params.filename,
data: partData
};
});
}));
});
return Promise.all(attachments);
}).then(function (attachments) {
console.log(attachments);
// =>
// [ { filename: 'cats.jpg', data: Buffer() },
// { filename: 'pay-stub.pdf', data: Buffer() } ]
});
I'm trying to remove Promises and turn the code into code using callbacks.
At the moment, I'm looping through all the attachments and when I print an individual attachment to the console I get:
Promise { <pending> }
How can I convert the code to regular callback code such that I can access the 'filename' and 'data' attributes of the attachment?
Actually, I don't understand why you need to go back from a promise to a callback but you can use the following code. It just a promise converter:
const promiseToCallback = function (promise) {
if (!isFn(promise.then)) {
throw new TypeError('Expected a promise');
}
return function (cb) {
promise.then(function (data) {
setImmediate(cb, null, data);
}, function (err) {
setImmediate(cb, err);
});
};
};
To use it
promiseToCallback(promise)(function(err, data) {
...
});

running parallel function with different inputs being trasnformed in the same input

I'm trying to run parellel functions with async.js
But when I try to update rows of a database, the async function doesn't handle different inputs.
It updates the same values for the where part, which always updates only one record. How can I turn local variables for parallel runs of the same function different?
This is my code:
exports.run_mercadolibre_jobs = function() {
var Model = require('../../models/index').Model;
var async = require("async");
var values = {
attributes: ['environment_hash'],
raw: true
};
Model
.findAll(values)
.then(function(accounts) {
async.map(accounts, function (account) {
module.exports.refresh_access_token(account.environment_hash);
});
});
}
exports.refresh_access_token = function(environment_hash) {
...
var env_hash = environment_hash;
where = { environment_hash: env_hash };
Model.findOne({where: where}).then(function (account) {
if (!account) {
// Item not found, create a new one
} else {
// Found an item, update it
values = {
refresh_token: body.refresh_token,
expires_in: expires_in
};
Model.update(values, {where: where})
.then(function () {
console.log('updated!');
})
.catch(function (err) {
console.log('error on update');
});
}
});
}
});
}

Categories