This code does not execute the promise of testAuthentication or pinFileToIPFS and i am curious if this is a node concept i am not familiar of.
function uploadToPinata(filename) {
const pinata = pinataSDK(process.env.PINATA_KEY, process.env.PINATA_SECRET_KEY);
pinata.testAuthentication().then((result) => {
//handle successful authentication here
console.log(result);
}).catch((err) => {
//handle error here
console.log(err);
});
const readableStreamForFile = fs.createReadStream(filename);
const options = {
pinataMetadata: {
name: "NYC_NFT_TESTING",
},
pinataOptions: {
cidVersion: 0
}
};
pinata.pinFileToIPFS(readableStreamForFile, options).then((result) => {
//handle results here
console.log(result);
}).catch((err) => {
//handle error here
console.log(err);
});
}
is there a problem with this code using a promise within a function? I attemped to make the function async but that did not help. This code works just fine outside of a function but not within one.
"does not execute the promise": this is a strange phrase. Promises are objects. They don't execute -- they are created. And your function really creates them. However, it does not do much when these promises are resolved.
The problem is that uploadToPinata will execute all of the synchronous code and return. But then there are still a promises pending. Although you have console.log that will be executed once the relevant promise has resolved, there is no signal to the caller of uploadToPinata that these promises have resolved.
It is probably easiest to use async and await:
async function uploadToPinata(filename) {
const pinata = pinataSDK(process.env.PINATA_KEY, process.env.PINATA_SECRET_KEY);
const result = await pinata.testAuthentication();
//handle successful authentication here
console.log("authentication result", result);
const readableStreamForFile = fs.createReadStream(filename);
const options = {
pinataMetadata: { name: "NYC_NFT_TESTING" },
pinataOptions: { cidVersion: 0 }
};
const result2 = await pinata.pinFileToIPFS(readableStreamForFile, options);
//handle results here
console.log("pinFileToIPFS result", result2);
}
The caller of this function will now receive a promise, so it should probably want to do something when that promise has resolved:
uploadToPinata(filename).then(() => {
console.log("authentication and file operation done")
}).catch(error => console.log("error", error));
Related
I have a function that is supposed to return a user's email from using the Firebase admin API getUser(uid) function,
function getEmail(uid){
var email;
admin.auth().getUser(uid)
.then((userRecord) => {
return userRecord.email;
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
}
But in my other function when I make a variable that calls the function,
email = getEmail(uid);
the value in email is undefined, because the getUser function has returned a promise. How do I make the function getEmail wait to get the value of userRecord before returning?
I've tried adding await statements in different parts of the function but I'm not sure how to do it correctly. I'm a beginner in using the Google API.
Return the Promise that you get from admin.auth().getUser(uid) in your getEmail function.
function getEmail(uid) {
return admin.auth().getUser(uid)
.then((userRecord) => {
return userRecord.email;
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
}
Then either use the returned Promise to chain a then callback.
getEmail(uid).then(email => {
console.log(email);
});
Or await it in an async function.
async function main() {
const email = await getEmail(uid);
console.log(email);
}
main();
Edit
As you explained in your comment below:
basically, I just want the code to run as if it were all synchronous/ line-by-line.
It's impossible to make asynchronous code synchronous, but it is possible to make it run line-by-line with async / await syntax. Promises that are being awaited in an async function will run line by line as you're telling the code to wait for it to resolve before going to the next line.
I've modified the code from your CodePen to include the aforementioned syntax. We're still using the same getEmail function that returns the promise from admin.auth().getUser(uid) and just wait for it to finish before doing something with the result.
function getEmail(uid) {
return admin.auth().getUser(uid)
.then((userRecord) => {
return userRecord.email;
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
}
app.post("/sendx", async (req, res) => {
const uid = req.body.x.user.uid;
const email = await getEmail(uid);
let verified = false;
/*console.log(email.substring(email.indexOf('#')));
if (email.substring(email.indexOf('#')) == "#xxx.edu") {
verified = true;
}*/
res.send({ verified });
});
I hope this clears it up.
I have three API calls which should be dependent on one another. The second API call should trigger only when the first succeeds.
With my current implementation, I'm getting a CORS error when the first API call is made and was able to catch the error in the catch block. However, I'm seeing that the second and third APIs calls are made irrespective of the error that got caught in the first API call.
Could anyone please advise?
const firstApiCall = async() => {
try {
await axios.post(
process.env.FIRST_API,
payload
);
]
} catch (err) {
console.log(`err`, err);
}
};
const secondApiCall = async() => {
try {
await axios.post(
process.env.SECOND_API,
payload
}
} catch (err) {
console.log(`err`, err);
}
};
const thirdApiCall = async() => {
try {
await axiosInstance.patch(
process.env.THIRD_API,
payload
);
} catch (err) {
console.log('err', err);
}
};
firstApiCall();
secondApiCall();
thirdApiCall();
You're calling the functions synchronously when you need to do it asynchronously:
async function performTasks() {
await firstApiCall();
await secondApiCall();
await thirdApiCall();
}
performTasks();
You can use the ES6 Promise implementation approacg. Therefore you should take a look to this ressource : [Promise][1]
With the promise approach you can react at each step / each API call.
[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
async await functions work only in their local scope.
For example:
const myFunc = async() => {
try{
//...
await foo();
//All the code below will be blocked till
//the promise return by foo function is resolved
}
catch{
//...
}
}
const main = () => {
myFunc();
otherFunc();
//Other function calls
//Regardless of using async await in myFunc,
//the code bellow myFunc will be executed as
//async await will work only in myFunc block scope
}
main()
What you can do is, use async await inside the main function, so that the functions would be called in an order
const main = async () => {
await myFunc();
await otherFunc();
}
I'm working on Ionic v4 with Angular.
In my project i use the BLE to communicate with a raspberry.
I have several step :
Search Device around me
Connect to this device
Activate Notification
Send Messages
Currently i have something like :
this.ble.scan().subscribe(result => {
if (device === theDeviceIWant) {
this.ble.connect(device.id).subscribe(result => {
this.ble.startNotification(infosaboutDevice).subscribe(result => {
// Message 1
this.ble.writeWithoutResponse(infos, message).then(result => {
// Message 2
this.ble.writeWithoutResponse(infos, message).then(result => {
// Message 3
this.ble.writeWithoutResponse(infos, message).then(result => {
// Message X
this.ble.writeWithoutResponse(infos, message).then(result => {
})
})
})
})
})
})
})
}
I want to do something like that :
this.myScan();
this.myConnect();
this.myNotification();
this.myMessage('Text 1');
this.myMessage('Text 2');
this.myMessage('Text X');
The probleme : My function ‘myConnect‘ don't wait the end of ‘myScan‘ to start. So somme stuff needed by ‘myConnect‘ is do in ‘myScan‘.
I already try to use ‘async/await‘ but does not work. I think i don't use it correctly :
await this.myConnect().then(async () => {
await this.myNotification().then(async () => {
await this.myMessage('03020000').then(async () => {
await this.myMessage('010100').then(async () => {
await this.myMessage('020200' + this.random.toString(16));
});
});
});
});
Help me to understand how to create a function who wait the end of the before one to start :D
Just use async/await OR then
await this.myConnect(); // this awaits the Promise returned by myConnect to be resolved
await this.myNotification(); // same for this Promise
await this.myMessage('03020000'); // and so on...
await this.myMessage('010100');
await this.myMessage('020200' + this.random.toString(16));
The keyword await makes JavaScript wait until that promise settles and
returns its result.
So you dont need to use then in await this.myConnect().then(()=>{});
use await this.myConnect();
Below is example which help you understand better
function SignalOne() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('Hello iam signal one');
}, 2000);
});
}
function SignalTwo() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('Hello iam signal Two');
}, 1000);
});
}
async function sendSignal() {
let one = await SignalOne();
let two = await SignalTwo();
console.log(one);
console.log(two);
}
sendSignal();
Try this:
async myScan() {
// do things
}
ngOnInit() {
const scan = this.myScan(); // myScan doesn't actually have to return here
await scan;
const connect = this.myConnect();
await connect;
// more stuff
}
This is essentially what Promises are made for.
A Promise is an object representing the eventual completion or failure
of an asynchronous operation.
You can read up about Promises here. Once you read thru that, I left an example for you below to demonstrate how to use a Promise:
//Wrap the operation you want to wait for in a Promise (in this case: setTimeout)
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('3 seconds have passed');
}, 3000);
});
//Once the operation is resolved the callback in the .then will be called
promise.then(val => document.querySelector('#target').innerHTML = val);
<div id="target">This message will change once the operation is resolved in 3 seconds.</div>
I would embrace Observables. Looking at what you want..
Search Device around me
Connect to this device
Activate Notification
Send Messages
1 and 2 would be chained with switchMap, as responses depend on each other. Then 3 and 4 could be performed in order, but not dependent on each other, therefore we could use concat with those. (If this is not correct flow, adjust accordingly with these two operators).
So I suggest the following:
import { never } from 'rxjs';
import { switchMap, concat } from 'rxjs/operators';
// ...
this.ble.scan().pipe(
switchMap((device) => {
if (device === theDeviceIWant) {
return this.ble.connect(device.id)
}
// terminates rest of code
return never();
}),
concat(
this.ble.startNotification(...),
this.ble.writeWithoutResponse(...)
)
).subscribe(data => console.log(data))
You're so close! Rather than using .then and async just use one or the other. Here are a few ways to accomplish what you are trying to do:
Using .then:
This is your typical chaining syntax. Promises can be chained using .then() and passing in a function. If the return value is a value (not a Promise) then it will resolve to that value. But if it did return a Promise then it will chain together and your next .then() will resolve to the "inner" async call result.
// Message 1
return this.ble.writeWithoutResponse(infos, message).then(result1 => {
// Message 2
return this.ble.writeWithoutResponse(infos, message);
}).then(result2 => {
// Message 3
return this.ble.writeWithoutResponse(infos, message);
)}.then(result3 => {
// Message X
return this.ble.writeWithoutResponse(infos, message);
}).then(result4 => { })
Using async/await
This approach achieves the same result but uses special keywords to automatically chain promises together. async/await allows you to skip the .then() and return calls so you can invoke your async functions as if they were synchronous.
// Message 1
let result1 = await this.ble.writeWithoutResponse(infos, message)
// Message 2
let result2 = await this.ble.writeWithoutResponse(infos, message);
// Message 3
let result3 = await this.ble.writeWithoutResponse(infos, message);
// Message X
let result4 = await this.ble.writeWithoutResponse(infos, message);
To learn more about Promise's and async javascript, check out these resources:
Promises on MDN
Promises on Google Web Fundamentals
Video on Async/Await
Take the following contrived example:
const housekeepingStuff = async function (data) {
const result = await notImportant(data);
result.more = 'yawn';
storeInDatabase(result);
};
const getStuff = async function () {
try {
const data = await getData();
data.extra = 'wow';
housekeepingStuff(data); // <---- don't want to await... but need to for error catching
return Promise.resolve(data);
} catch (err) {
return Promise.reject(err);
}
};
try {
const myData = await doSomeStuff();
res.send(myData);
} catch (err) {
console.log(err);
res.sendStatus(400);
}
I want to return the data from getStuff () ASAP without waiting for housekeepingStuff() but if I don't await that function then I have an uncaught error.
I could call housekeepingStuff() outside the getStuff() function, after getting and sending the data to whoever wants it:
try {
const myData = await doSomeStuff();
res.send(myData);
await housekeepingStuff(data); // <---- am awaiting but who cares because nothing follows
} catch (err) {
console.log(err);
res.sendStatus(400);
}
But that doesn't seem right because I don't want to have to remember to call housekeepingStuff() every time I call doSomeStuff()... it should ideally be handled "internally".
What is the correct approach here?
A promise (or async) function has 2 possible outcomes:
A successful outcome
An error outcome
To get either outcome, you must wait for it. You can't wait for 1 condition and not for the other, because the entire thing needs to execute so you can find out what the outcome was.
Otherwise you're really asking the javascript engine: Please predict for me if the function will fail, and if it does, await it.
The correct approach therefore is to just await it.
However, if you don't care about either successful or failed outcomes of this function, just call the function via another async function that eats all the errors:
async function doSomeStuffAndIgnoreError() {
try {
await doSomeStuff();
} catch (e) {
console.error(e);
}
}
I am trying to make a simple weather application based on Node.js, like this one. My problem is that every mechanism I see is based on promises, and I don't understand the concept.
So, the code I see everywhere is like:
yrno.getWeather(LOCATION).then((weather) => {
weather.getFiveDaySummary().then((data) => console.log('five day summary', data));
weather.getForecastForTime(new Date()).then((data) => console.log('current weather', data));
})
.catch((e) => {
console.log('an error occurred!', e);
});
However, I was unable to find a way to resolve these promises and save the five day summary to a variable for later use.
How do I proceed?
Thanks,
Robin
Assign the Promise returned from yrno.getWeather(LOCATION) call to a variable.
Use Promise.all() to return results from both weather.getFiveDaySummary() and weather.getForecastForTime(new Date()) calls.
Chain .then() to the result of call to get the data at initial and subsequent .then() chained to variable identifier which returned initial Promise values.
let weatherData = yrno.getWeather(LOCATION).then(weather => {
// note `return`, alternatively omit `return` and `{`, `}` at arrow function
// .then(weather => Promise.all(/* parameters */))
return Promise.all([weather.getFiveDaySummary()
, weather.getForecastForTime(new Date())]);
});
weatherData
// `results` is array of `Promise` values returned from `.then()`
// chained to `yrno.getWeather(LOCATION).then((weather)`
.then(results => {
let [fiveDaySummary, forecastForTime] = results;
console.log('five day summary:', fiveDaySummary
, 'current weather:', forecastForTime);
// note `return` statement, here
return results
})
.catch(e => {
// `throw` `e` here if requirement is to chain rejected `Promise`
// else, error is handled here
console.log('an error occurred!', e);
});
// weatherData
// .then(results => { // do stuff with `results` from first `weatherData` call })
// .catch(e => console.log(e));
An alternative to using promises directly is to use await/async.
// weather.js
const yrno = require('yr.no-forecast')({
version: '1.9', // this is the default if not provided,
request: {
// make calls to locationforecast timeout after 15 seconds
timeout: 15000
}
});
const LOCATION = {
// This is Dublin, Ireland
lat: 53.3478,
lon: 6.2597
};
async function getWeather() {
let weather = await yrno.getWeather(LOCATION);
let fiveDaySummary = await weather.getFiveDaySummary();
let forecastForTime = await weather.getForecastForTime(new Date());
return {
fiveDaySummary: fiveDaySummary,
forecastForTime: forecastForTime,
}
}
async function main() {
let report;
try {
report = await getWeather();
} catch (e) {
console.log('an error occurred!', e);
}
// do something else...
if (report != undefined) {
console.log(report); // fiveDaySummary and forecastForTime
}
}
main(); // run it
you can run this (node.js 7) with:
node --harmony-async-await weather
You can use await/async on older targets by using Babel or Typescript to transpile it down for you.
Bonus (based off your comments) - I wouldn't do it this way, but just to show you it can be done:
const http = require('http');
const port = 8080;
http.createServer(
async function (req, res) {
let report = await getWeather(); // see above
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write("" + JSON.stringify(report.fiveDaySummary));
res.end('Hello World\n');
})
.listen(port);
again with node --harmony-async-await weather or transpile it.