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));
Summary: creating my own API that returns epoch time, and it involves using an express.js server, but it's running res.send() before the function call. I referenced this page, but it didn't help. Here's what I have:
app.get('/timestampAPI', async (req, res,) => {
try {
let finalResult = await getTimeStamp();
res.send({ something: finalResult });
} catch (error) {
console.log(error);
}
});
It'll start to run the function getTimeStamp(), and before that function finishes, it runs the res.send() function which shows up as '{}' because finalResult doesn't have a value. getTimeStamp() is an async function. I'm unsure of what I'm doing wrong.
Edit:
getTimeStamp() function:
async function getTimeStamp() {
await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
return response.data;
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
});
}
Another edit: yes, the API referenced above does return the current epoch time, but CORS is blocking my other site from accessing it directly, so I can't use it on that site, which is why I'm using node.js for it so that I can allow myself to access it through my node.js program. Couldn't think of another way
returning value of the then method does not return from getTimeStamp function you should write you code in resolve pattern or using await like below
try this, make sure you write correct field name in response object
async function getTimeStamp() {
try{
const res = await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
return res.data
}catch(error){
throw error
}
As an alternative to Mohammad's answer you can also use returning getTimeStamp function's result as a promise and it can solve your problem.
async function getTimeStamp() {
return new Promise((resolve, reject) => {
axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
resolve(response.data);
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
reject(error);
});
})
}
Or you would also replace await with return in getTimeStamp function in your code if you don't want to return promise.(Which is not I recommend.). You should also throw the error in catch block which is generated in getTimeStamp function for catching the error in try-catch block that you use to call app.get(...).
I have successfully called a sequence of soap webservice methods using nodejs/javascript, but using callbacks... right now it looks something like this:
soap.createClient(wsdlUrl, function (err, soapClient) {
console.log("soap.createClient();");
if (err) {
console.log("error", err);
}
soapClient.method1(soaprequest1, function (err, result, raw, headers) {
if (err) {
console.log("Security_Authenticate error", err);
}
soapClient.method2(soaprequest2, function (err, result, raw, headers) {
if (err) {
console.log("Air_MultiAvailability error", err);
}
//etc...
});
});
});
I'm trying to get to something cleaner using Promise or async, similar to this (based on the example in the docs here https://www.npmjs.com/package/soap) :
var soap = require('soap');
soap.createClientAsync(wsdlURL)
.then((client) => {
return client.method1(soaprequest1);
})
.then((response) => {
return client.method2(soaprequest2);
});//... etc
My issue is that in the latter example, the soap client is no longer accessible after the first call and it typically returns a 'not defined' error...
is there a 'clean' way of carrying an object through this kind of chaining to be used/accessible in subsequent calls ?
Use async/await syntax.
const soap = require('soap');
(async () => {
const client = await soap.createClientAsync(wsdlURL);
cosnt response = await client.method1Async(soaprequest1);
await method2(soaprequest2);
})();
Pay attention to Async on both createClient and method1
In order to keep the chain of promises flat, you can assign the instance of soap to a variable in the outer scope:
let client = null;
soap.createClientAsync(wsdlURL)
.then((instance) => {
client = instance
})
.then(() => {
return client.method1(soaprequest2);
})
.then((response) => {
return client.method2(soaprequest2);
});
Another option would be nested chain method calls after the client is resolved:
soap.createClientAsync(wsdlURL)
.then((client) => {
Promise.resolve()
.then(() => {
return client.method1(soaprequest2);
})
.then((response) => {
return client.method2(soaprequest2);
});
})
I'm currently struggling to get variable values from one node.js module into another. This is my current problem:
I am fetching data from a REST API via https-request:
// customrequest.js
sendRequest( url, function( data, err ) {
if(err) {
console.log('--- Error ---');
console.log( err );
}
else {
console.log('--- Response ---');
console.log(data);
// output: data
return data;
}
module.exports = { sendRequest }
And my index.js file:
// index.js
let sendRequest = require('./customrequest');
let req;
req = sendRequest('google.com');
console.log(req);
// output: undefined
// how can I get the variable set, when request is getting data in response?
I totally understand, that the request to an API takes some time for the response. One solution is, that I just put everything into one js file. But as my project will get bigger over time, the modular approach is my goto-solution. Any suggestions on how to solve this?
Node uses callbacks for this situation. Try something like this:
// customrequest.js
sendRequest(url, callback)
module.exports = { sendRequest }
// index.js
let sendRequest = require('./customrequest');
let req = sendRequest('google.com', function (data, err) {
if (err) {
//handle error here
}
console.log(data);
};
// output: undefined
// how can I get the variable set, when request is getting data in response?
Thanks. The problem I encounter is somewhat different. I solved it with this code snippets … using async and await.
// request.js
const fetch = require('node-fetch')
async function myRequest (somestring) {
try {
let res = await fetch('https://api.domain.com/?endpoint='+somestring)
if (res.ok) {
if (res.ok) return res.json()
return new Error (res.status)
}
} catch (err) {
console.error('An error occurred', err)
}
}
module.exports = { myRequest }
// index.js
const request = require('./requests')
const myRequest = request.myRequest
let myVar;
myRequest('somestring')
.then(res => myVar = res.result)
setInterval(() => {
myRequest('somestring')
.then(res => myVar = res.result)
console.log(myVar)
}, 1000)
The async function and awaits return a promise. This promise is, when resolved, assigned to a variable.
I want to get an api and after that call another one. Is it wisely using a code like this in javascript?
fetch(url, {
method: 'get',
}).then(function(response) {
response.json().then(function(data) {
fetch(anotherUrl).then(function(response) {
return response.json();
}).catch(function() {
console.log("Booo");
});
});
})
.catch(function(error) {
console.log('Request failed', error)
});
Fetch returns a promise, and you can chain multiple promises, and use the result of the 1st request in the 2nd request, and so on.
This example uses the SpaceX API to get the info of the latest launch, find the rocket's id, and fetch the rocket's info.
const url = 'https://api.spacexdata.com/v4';
const result = fetch(`${url}/launches/latest`, { method: 'get' })
.then(response => response.json()) // pass the data as promise to next then block
.then(data => {
const rocketId = data.rocket;
console.log(rocketId, '\n');
return fetch(`${url}/rockets/${rocketId}`); // make a 2nd request and return a promise
})
.then(response => response.json())
.catch(err => {
console.error('Request failed', err)
})
// I'm using the result const to show that you can continue to extend the chain from the returned promise
result.then(r => {
console.log(r.first_stage); // 2nd request result first_stage property
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
There is not an issue with nesting fetch() calls. It depends on what you are trying to achieve by nesting the calls.
You can alternatively use .then() to chain the calls. See also How to structure nested Promises
fetch(url)
.then(function(response) {
return response.json()
})
.then(function(data) {
// do stuff with `data`, call second `fetch`
return fetch(data.anotherUrl)
})
.then(function(response) {
return response.json();
})
.then(function(data) {
// do stuff with `data`
})
.catch(function(error) {
console.log('Requestfailed', error)
});
This is a common question people get tripped up by when starting with Promises, myself included when I began. However, first...
It's great you're trying to use the new Fetch API, but if I were you I would use a XMLHttpRequest implementation for now, like jQuery AJAX or Backbone's overridden implementation of jQuery's .ajax(), if you're already using these libraries. The reason is because the Fetch API is still so new, and therefore experimental at this stage.
With that said, people definitely do use it, but I won't in my own production code until it's out of "experimental" status.
If you decide to continue using fetch, there is a polyfill available. NOTE: you have to jump through extra hoops to get error handling to work properly, and to receive cookies from the server. If you're already loading jQuery, or using Backbone, just stick with those for now; not completely dreadful, anyway.
Now onto code:
You want a flat structure, else you're missing the point of Promises. It's not wise to nest promises, necessarily, because Promises solve what nested async callbacks (callback hell) could not.
You will save yourself time and energy, and produce less buggy code by simply using a more readable code structure. It's not everything, but it's part of the game, so to speak.
Promises are about making asynchronous code retain most of the lost properties
of synchronous code such as flat indentation and one exception
channel.
-- Petka Antonov (Bluebird Promise Library)
// run async #1
asyncGetFn()
// first 'then' - execute more async code as an arg, or just accept results
// and do some other ops
.then(response => {
// ...operate on response data...or pass data onto next promise, if needed
})
// run async #2
.then(asyncGetAnotherFn)
.then(response => {
// ...operate on response data...or pass data onto next promise, if needed
})
// flat promise chain, followed by 'catch'
// this is sexy error handling for every 'then' above
.catch(err => {
console.error('Request failed', err)
// ...raise exeption...
// ... or, retry promise...
})
I didn't saw an answer with the syntactic sugar of async/await, so I'm posting my answer.
Another way to fetch "inside" another fetch in javascript is like -
try {
const response = await fetch(url, {method: 'get'});
const data = response.json();
//use the data...
const anotherResponse = await fetch(url, {method: 'get'});
const anotherdata = anotherResponse.json();
//use the anotherdata...
} catch (error) {
console.log('Request failed', error) ;
}
So actually you call url after url one by one.
This code will work inside async context.
I would use either an array of fetches instead or an array of urls, both in the order you would like to execute them. Then use reduce to execute them in sequence. This way it is much more scalable.
const urls = [
'https://api.spacexdata.com/v4/launches/latest',
'https://api.spacexdata.com/v4/launches/latest',
'https://api.spacexdata.com/v4/launches/latest'
];
// handle the fetch logic
// and handle errors
const handleFetch = async (url) => {
const resp = await fetch(url).catch(console.error);
return resp.json()
}
// reduce fetches, receives the response
// of the previous, log it (and maybe use it as input)
const reduceFetch = async (acc, curr) => {
const prev = await acc;
console.log('previous call:', prev);
return handleFetch(curr);
}
const pipeFetch = async urls => urls.reduce(reduceFetch, Promise.resolve(''));
pipeFetch(urls).then(console.log);
Is it wisely using a code like this in javascript?
Yes. Your code is fine.
Except that after the second request,
fetch(anotherUrl).then(function(response) {,
I would replace return response.json();
with response.json().then(function(data2) { – just as after the
first request.
The variable data2 will then contain the response body of the inner
URL request, as desired.
This means that – whatever you want to do with data2, you must do it
inside this second callback (since you don't return a promise.)
Also, a few more printouts will help to understand what is happening.
1. The original code – slightly modified
After making those changes, here is a Stack Snippet containing your
code:
1
const url = 'https://jsonplaceholder.typicode.com/todos/1';
const anotherUrl = 'https://jsonplaceholder.typicode.com/todos/4';
fetch(url, {
method: 'get'
}).then(function (response) {
response.json().then(function (data) {
console.log('Response body of outer "url":');
console.log(JSON.stringify(data) + '\n\n');
fetch(anotherUrl).then(function (response) {
response.json().then(function (data2) {
console.log('Response body of inner "anotherUrl":');
console.log(JSON.stringify(data2) + '\n\n');
});
}).catch(function () {
console.log('Booo');
});
});
})
.catch(function (error) {
console.log('Request failed', error);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
which is fine really, although the fat arrow style is more common
these days for defining a function.
2. The code refactored
Here is a refactored version of your code.
It has an inner chained/nested request – fetch(urlInner) – that
depends on data retrieved from a previous/outer request: fetch (urlOuter).
By returning the promises of both the outer and the inner URL fetches,
it is possible to access/resolve the promised result later in the code:
2
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://jsonplaceholder.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner)
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch - ' + urlInner);
console.error(err);
});
}).catch(err => {
console.error('Failed to fetch - ' + urlOuter);
console.error(err);
});
resultPromise.then(jsonResult => {
console.log('Result - the title is "' + jsonResult.title + '".');
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
Note that no indentation is deeper than eight spaces.
3. Advantages of this code style
This is clearly a nested style of writing the code – meaning that the
chained request fetch(urlInner) is indented and made inside the
callback of the first request fetch(urlOuter).
Yet, the indentation tree is reasonable, and this style resonates well
with my intuition about chaining requests. – But more importantly,
this style makes it possible to write error messages that pinpoint
which URL failed.
Run the snippet below to see how the error message tells that it is the
inner/second URL that causes the error:
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://VERY-BAD-URL.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner)
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch - ' + urlInner);
console.error(err);
});
}).catch(err => {
console.error('Failed to fetch - ' + urlOuter);
console.error(err);
});
resultPromise.then(jsonResult => {
console.log('Result - the title is "' + jsonResult.title + '".');
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
4. Flattening all occurrences of .then()?
Inspired by others, you may be tempted to flatten all occurrences of
.then(), like below.
I would advise against doing this – or at least think twice before
doing it. Why?
In the absence of errors, it doesn't matter.
If there are errors, such a style will force less distinct error
messages:
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://VERY-BAD-URL.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner);
})
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch one or more of these URLs:');
console.log(urlOuter);
console.log(urlInner);
console.log(err);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
The code is nicely flat, but the error caught at the end cannot decide
which of the URL requests that failed.
1 All snippets of this answer comply with the
JavaScript Semistandard Style.
2 About line 11 – return fetch(urlInner) – it is
very easy to forget to return the fetch.
(I once forgot it even after writing this answer.)
If you do forget it, resultPromise will not contain any promise at
all.
The last three lines in the snippet will then fail – they will output
nothing.
The result fails completely!
just some ways of doing it.
1, using async -await
app.get("/getemployeedetails/:id", async (req, res) => {
const id = req.params.id;
const employeeUrl = "http://localhost:3000/employee/" + id;
try {
const response = await fetch(employeeUrl);
const employee = await response.json();
const projectUrl = "http://localhost:3000/project/" + employee.project_id;
const response1 = await fetch(projectUrl);
const project = await response1.json();
const result = {
...employee,
...project,
};
res.send(result);
} catch (error) {
console.log("getData: ", error);
}
});
2, chaining of then
app.get("/getemployeedetails/:id", (req, res) => {
const id = req.params.id;
const employeeUrl = "http://localhost:3000/employee/" + id;
let employeeResponse = null;
fetch(employeeUrl)
.then((employee) => employee.json())
.then((resp) => {
employeeResponse = resp
const projectUrl =
"http://localhost:3000/project/" + employeeResponse.project_id;
return fetch(projectUrl);
})
.then((project) => project.json())
.then((projectResponse) => {
const result = {
...employeeResponse,
...projectResponse,
};
res.send(result);
})
.catch((err) => console.log(err));
});
3, chaining in a better way
app.get("/getemployeedetails/:id", (req, res) => {
const id = req.params.id;
getEmployeeResponse(id).then((employeeResponse) => {
getProjectResponse(employeeResponse.project_id)
.then((projectResponse) => {
const result = {
...employeeResponse,
...projectResponse,
};
res.send(result);
})
.catch((err) => console.log(err));
});
});
function getEmployeeResponse(id) {
return new Promise((resolve, reject) => {
const employeeUrl = "http://localhost:3000/employee/" + id;
fetch(employeeUrl)
.then((employee) => employee.json())
.then((resp) => resolve(resp))
.catch((err) => reject(err));
});
}
function getProjectResponse(id) {
return new Promise((resolve, reject) => {
const projectUrl = "http://localhost:3000/project/" + id;
fetch(projectUrl)
.then((project) => project.json())
.then((resp) => resolve(resp))
.catch((err) => reject(err));
});
}
you decide.
I suggest using axios, is much better and you don't have to deal with JSON format. Also, the code looks cleaner and is easier to understand.
axios.get(firstUrl).then((resp1) => {
// Handle success of first api
axios.get(secondUrl).then((resp2) => {
return resp2.data
}).catch((error) => { /* Handle error of second api */ });
}).catch((error) => { /* Handle error of first api */ });
Blockquote from LogRocket.com:
As with Fetch, Axios is promise-based. However, it provides a more
powerful and flexible feature set.
Advantages of using Axios over the native Fetch API include:
Request and response interception
Streamlined error handling
Protection against XSRF
Support for upload progress
Response timeout
The ability to cancel requests
Support for older browsers
Automatic JSON data transformation