Async module returning promise [object Promise] - javascript

I am trying to export the value with instrument variable. however data is returning as [object Promise] than object. How can I assign module variable with the final result rather than the promise object.
var instruments = {
data: async () => {
return new Promise((resolve, reject) => {
/// Respond after retrieving the data
resolve({result : "...." }
);
}
}
var symbols = async () => {
const res = await instruments.data();
return res;
}
module.exports.instrument = symbols().then((data) => {
console.log('data');
return data;
}).catch((e) => {
console.log('error');
return {}
});

It looks like you want a singleton cache. Here is a basic implementation
cache.js
let data = {}
module.exports = {
getData: () => {
return data
},
setData: newData => {
data = newData
return
},
}
No need for async here. I would separate this code with the code that retrieves data.
fetchData.js
const cache = require('./cache')
const fetchData = () => {} // fetch data code here
fetchData().then(data => {
cache.setData(data)
})

try this
var instruments = {
data: () => {
return new Promise((resolve, reject) => {
/// Respond after retrieving the data
resolve({result : "...." });
}
}
var symbols = async () => {
const res = await instruments.data();
return res;
}
module.exports.instrument = symbols;
then import instrument method to call and then call
const instrument = require("./filepath");
instrument().then((data) => {
console.log('data');
}).catch((e) => {
console.log(e);
});

If your async function instruments.data() called, it'll await return Promise.
just append await at return for your expected result.
var instruments = {
data: async () => {
return await new Promise((resolve, reject) => {
// Respond after retrieving the data
resolve({result : "...." });
}
}
or remove async. it's same as above.
var instruments = {
data: () => {
return new Promise((resolve, reject) => {
// Respond after retrieving the data
resolve({result : "...." });
}
}

Related

How to replace a push with a splice js

When entering a screen, 5 promises are loaded automatically, I use a promise.all, the problem is that they are executed randomly, within each function I use a push where I put the information.
The problem is that I have to change the push for a splice because the promise.all is loaded randomly and with the push I can't know which place to assign to each information of each "function". Here is my code:
At the beginning it loads the promises
ngOnInit(): void {
Promise.all([this.getData1(), this.getData2()]).then(values => {
console.log(values)
this.processing = true;
}).catch(reason => {
console.log('error get data',reason)
});
}
I only put 2 as an example but in the other functions it is the same
public getData1() {
return new Promise((resolve, reject) => {
this.createService.getServiceData1().subscribe(
(response: any) => {
let customFieldOption: CustomFieldOption = new CustomFieldOption();
this.opcionServicio = response;
this.opcionesServicio.push(this.opcionServicio);
this.servicio.push(this.opcionesServicio[0].ticket_field.title)
customFieldOption.id = this.opcionServicio.ticket_field.id;
customFieldOption.name = this.opcionServicio.ticket_field.title;
this.customFieldOptions.push(customFieldOption);
resolve(true);
},
(error) => {
console.log(error);
reject(true);
}
);
});
}
public getData2() {
return new Promise((resolve, reject) => {
this.createService.getServiceData2().subscribe(
(response: any) => {
let customFieldOption: CustomFieldOption = new CustomFieldOption();
this.opcionServicio = response;
this.opcionesServicio.push(this.opcionServicio);
this.servicio.push(this.opcionesServicio[0].ticket_field.title)
customFieldOption.id = this.opcionServicio.ticket_field.id;
customFieldOption.name = this.opcionServicio.ticket_field.title;
this.customFieldOptions.push(customFieldOption);
resolve(true);
},
(error) => {
console.log(error);
reject(true);
}
);
});
}
You can use an array with indexes instead of push or an object with static keys.
Example 1:
You can put data1 to this.opcionesServicio[0] and data2 to this.opcionesServicio[1]. Then you know that they can be always accessed by the same index.
opcionesServicio = [];
public getData1(dataIndex = 0) {
return new Promise((resolve, reject) => {
this.createService.getServiceData1().subscribe((response: any) => {
this.opcionesServicio[dataIndex] = respoosne;
});
});
}
public getData2(dataIndex = 1) {
return new Promise((resolve, reject) => {
this.createService.getServiceData2().subscribe((response: any) => {
this.opcionesServicio[dataIndex] = respoosne;
});
});
}
// Access
const data1 = this.opcionesServicio[0];
const data2 = this.opcionesServicio[1];
Example 2:
You can store the data in an object instead.
data1 goes to this.opcionesServicio['data1'] and data2 to this.opcionesServicio['data2']. Then you can access them by the data1, data2 keys.
opcionesServicio = {};
public getData1(dataName = 'data1') {
return new Promise((resolve, reject) => {
this.createService.getServiceData1().subscribe((response: any) => {
this.opcionesServicio[dataName] = respoosne;
});
});
}
public getData2(dataName = 'data2') {
return new Promise((resolve, reject) => {
this.createService.getServiceData2().subscribe((response: any) => {
this.opcionesServicio[dataName] = respoosne;
});
});
}
const data1 = this.opcionesServicio['data1'];
const data2 = this.opcionesServicio['data2'];

Chaining three different async functions

I have three async functions but the third function is running before the second one resolves. What is wrong here?
async function getSet () {
//get settings from asyncstorage and setstate
}
async function pairs () {
//fetch data and set another state
}
async function fetchIt () {
//fetch another data and set a third state
}
useEffect(() => {
getSet()
.then(pairs())
.then(fetchIt())
.then(() => {
setLoading(false);
});
}, []);
fetchIt() is running before pairs()
The calls aren't chained properly. To make it simpler use async await:
useEffect(() => {
(async function () {
await getSet();
await pairs();
await fetchIt();
setLoading(false);
})();
}, []);
If each call depends on the result of the last it looks like
const r1 = await getSet();
const r2 = await pairs(r1);
// etcetera
You haven't chained the 'then's properly. They must return a promise as well. Read more here.
const getSet = async() => {
//get settings from asyncstorage and setstate
return new Promise((resolve, reject) => {
resolve('getSet');
});
}
const pairs = async() => {
//fetch data and set another state
return new Promise((resolve, reject) => {
resolve('pairs');
});
}
const fetchIt = async() => {
//fetch another data and set a third state
return new Promise((resolve, reject) => {
resolve('fetchIt');
});
}
getSet()
.then(response => {
console.log(response);
return pairs();
})
.then(response => {
console.log(response);
return fetchIt();
})
.then(response => {
console.log(response);
// setLoading(false);
});

Second function not called asynchronously in nodejs

I am trying to call some function using a single express router , I want to call them in order, meaning that I don't want getLaps() function to execute before get streams function has done all the work , so I tried to use some solutions I found on the internet but it didn't work, the second function doesn't execute. Please help.
Here is my code :
router.get("/", async (req, res,done) => {
res.status(201).send('created user')
return getLaps(function () {
getStreams(function () {
});
});
// await getStreams();
// await getLaps();
// console.log("hey")
});
Here is the get laps function :
function getLaps(req) {
const access_token = '75f2d92fdc445033312854d775e039b6c5bf04e7';
//for test 3756582581,
const idL = [5567017025, 5566531480];
const stravaClient = StravaClientService.getClient(access_token);
const activityService = StravaActivityService(stravaClient);
var params = {
TableName: "run-id",
Key: {
"id": "15428785",
}
};
console.log("cool laps")
docClient.get(params, async function (err, data) {
if (err) {
console.log("Error", err);
} else {
}
idL.map((id, index) => setTimeout(() => activityService.listLaps(id), (5 + index) * 60)
)
//data.Item.json
});
}
and the streams function :
function getStreams(req) {
const idS = [
5567017025, 5566531480
];
const stravaClient = StravaClientService.getClient(access_token);
const activityService = StravaActivityService(stravaClient);
var params = {
TableName: "run-id",
Key: {
"id": "15428785",
}
};
console.log("cool streams")
docClient.get(params, async function (err, data) {
if (err) {
console.log("Error", err);
} else {
idS.map((id, index) => setTimeout(() => activityService.streamActivity(id), (5 + index) * 60))
console.log("got the streams")
}
});
}
in your getStream and getLaps function return promises instead of other object/Stuff like
async function getStream(){
return new Promise(async (resolve, reject){
//Do something
//where you want to return something just call resolve function like
resolve()
//if you want some output of getStream() just pass it to resolve function
//const result = 'I'm result'
resolve(result)
})
}
do same thing with the laps function and in your router call them with await keyword

Can't save values using indexedDB

Hello I am stuck with indexedDB. When I try to store an array of links, it fails with no errors or exceptions.
I have two code examples. This one works fine:
export const IndexedDB = {
initDB(): Promise<string> {
return new Promise((resolve, reject) => {
const open = indexedDB.open("MyDB", 1);
open.onupgradeneeded = function () {
open.result.createObjectStore("store", { keyPath: "id" });
resolve("Database initialized successfully...");
};
open.onerror = function (err) {
reject(err);
};
open.onsuccess = function () {
resolve("Database initialized successfully...");
};
});
},
getAll(): Promise<Values> {
return new Promise((resolve, reject) => {
const open = indexedDB.open("MyDB", 1);
open.onerror = function (err) {
reject(err);
};
open.onsuccess = function () {
const tx = open.result.transaction("store", "readonly");
const store = tx.objectStore("store");
const getFromStore = store.getAll();
getFromStore.onerror = function (err) {
reject(err);
};
getFromStore.onsuccess = function () {
resolve(getFromStore.result);
};
};
});
},
putMany(values: Values): Promise<void> {
return new Promise((resolve, reject) => {
const open = indexedDB.open("MyDB", 1);
open.onerror = function (err) {
reject(err);
};
open.onsuccess = function () {
values.forEach((value: Value) => {
const tx = open.result.transaction("store", "readwrite");
const store = tx.objectStore("store");
const putInStore = store.put(value);
putInStore.onerror = function (err) {
reject(err);
};
});
resolve();
};
});
},
};
App.tsx:
export const saveValues = (values: Values): Promise<void> => {
IndexedDB.putMany(values);
};
export const App: React.FunctionComponent = () => {
const valuesForTest: Values = [
{
id: Math.random(),
text: "Hello world!"
},
{
id: Math.random(),
text: "Hello world!"
},
{
id: Math.random(),
text: "Hello world!"
}
];
useEffect(() => {
saveValuesToDB(valuesForTest);
}, []);
return (
<SomeComponent/>
);
};
And this one always fails. No errors or exceptions at all. The data just isn't saved.
The main difference is just data types. The first example uses the "Values" type, and the second uses the "Links" type.
export const IndexedDB = {
initDB(): Promise<string> {
return new Promise((resolve, reject) => {
const open = indexedDB.open("MyDB", 1);
open.onupgradeneeded = function () {
open.result.createObjectStore("store", { keyPath: "href" });
resolve("Database initialized successfully...");
};
open.onerror = function (err) {
reject(err);
};
open.onsuccess = function () {
resolve("Database initialized successfully...");
};
});
},
getAll(): Promise<Links> {
return new Promise((resolve, reject) => {
const open = indexedDB.open("MyDB", 1);
open.onerror = function (err) {
reject(err);
};
open.onsuccess = function () {
const tx = open.result.transaction("store", "readonly");
const store = tx.objectStore("store");
const getFromStore = store.getAll();
getFromStore.onerror = function (err) {
reject(err);
};
getFromStore.onsuccess = function () {
resolve(getFromStore.result);
};
};
});
},
putMany(values: Links): Promise<void> {
return new Promise((resolve, reject) => {
const open = indexedDB.open("MyDB", 1);
open.onerror = function (err) {
reject(err);
};
open.onsuccess = function () {
values.forEach((value: Link) => {
const tx = open.result.transaction("store", "readwrite");
const store = tx.objectStore("store");
const putInStore = store.put(value);
putInStore.onerror = function (err) {
reject(err);
};
});
resolve();
};
});
},
};
App.tsx:
export const saveValues = (values: Links): Promise<void> => {
IndexedDB.putMany(values);
};
export const App: React.FunctionComponent = () => {
const valuesForTest: Links = [
{
href: "https://somelink1.com/",
name: "Link"
},
{
href: "https://somelink2.com/",
name: "Link"
},
{
href: "https://somelink3.com/",
name: "Link"
},
];
useEffect(() => {
saveValuesToDB(valuesForTest);
}, []);
return (
<SomeComponent/>
);
};
Can you help me?
If you created the database with the first code snippets, your "store" object store will be using id as keyPath. If you want to change this to href as in your second snippet, delete the database first (in the browser devtools), then run your second snippet.
Kindly note that if you want to make schema changes to an existing database (without deleting it), you will have to pass a higher version number to indexedDB.open to trigger your onupgradeneeded callback: indexedDB.open("MyDB", 2);. If the database exists with the same version, that callback will (obviously) not be executed because it doesn't need upgrading.
Also note that if you want to use both your code snippets to store different things (values and links), use separate object stores for them: createObjectStore("values", { keyPath: "id" }) and createObjectStore("links", { keyPath: "href" })
Last but not least, for easier IndexedDB usage I can really recommend to use AceBase (fullblown realtime database) or Dexie (simple IndexedDB wrapper) instead. Those are easy to use and handle all IndexedDB plumbing!
EDIT: In your putMany method I also see you call resolve in the open.onsuccess callback, instead of waiting until all of your put operations have succeeded. That's why you don't get an error, reject will be called after resolve so that does nothing.

Async / Await, how do I force my function to wait until promise is resolved before it continues?

I would like my function to execute until the nextPageToken is null. When I execute the function the first time, it waits for the promise to be resolved. However as soon there is a nextPageToken present on the response, the function does not wait for the response and a stack overflow occurs.
It seems that f() is not suspended on the when await p.then() is called.
Am I totally misunderstanding how async/await works?
Any help would be greatly appreciated...
public apiResult2(path: string, objectName: string, params: any = { }) {
let returnArray = [];
const p = new Promise<any> ((resolve, reject) => {
gapi.load('auth2:client', () => {
gapi.client.request({
path: path,
params: params
}).then(response => {
// resolve this promise with the first key in the response object.
resolve(response.result);
}, reason => {
console.log(reason);
reject(reason.result);
});
});
});
let f = async () => {
let nextPageToken = null;
do {
let r = await p.then(result => {
if (result.hasOwnProperty(objectName)) {
for (let obj of result[objectName]) {
returnArray.push(obj);
}
}
if (result.hasOwnProperty('nextPageToken')) {
params.nextPageToken = result.nextPageToken;
return result.nextPageToken;
// nextPageToken = result.nextPageToken;
} else {
params.nextPageToken = null;
return null;
// nextPageToken = null;
}
});
nextPageToken = r;
console.log(r);
} while (nextPageToken);
};
f();
return returnArray;
}
If your function needs to "await" some async call, then it must also be async. Your function apiResult2 is not going to wait for f to be finished, in order to return returnArray.
EDIT:
The main issue here is that you are trying to reuse the promise p to make different requests, but this is not possible. The promise p will be initialized with the parameters for the first request, and all the calls to p.then will be fulfilled with the same result: the response for the first page request.
I made some small changes to your code, and got it working with a mocked interface:
const apiResult2 = async (path: string, objectName: string, params: any = { }) => {
const requestPage = async () => new Promise<any> ((resolve, reject) => {
gapi.load('auth2:client', () => {
gapi.client.request({
path: path,
params: params
}).then(response => {
// resolve this promise with the first key in the response object.
resolve(response.result);
}, reason => {
console.log(reason);
reject(reason.result);
});
});
});
let returnArray: string[] = [];
do {
const page = await requestPage();
if (page.hasOwnProperty(objectName)) {
for (let obj of page[objectName]) {
returnArray.push(obj);
}
}
if (page.hasOwnProperty('nextPageToken')) {
params.nextPageToken = page.nextPageToken;
} else {
params.nextPageToken = null;
}
} while (params.nextPageToken);
return returnArray;
}
Usage example:
apiResult2(path, objectName, params).then(
result => console.log(result),
err => console.log('error', err)
);

Categories