I am trying to figure out how to make the second Request run after the first request returned a response.I tried to search on google, but I'm kinda new to Postman and I'm not sure what should I look for.
I tried to do something like:
pm.sendRequest(req1, function(err, res) {
pm.sendRequest(req2, function(err, done)
)});
But It didnt work
while(documentLength>0)
{
pm.sendRequest(listDocumentsRequest, function(err, res){
pm.environment.set('dossierId',res.json().documentsList[index].subDossierId)
pm.environment.set('documentId',res.json().documentsList[index].documentId)
});
pm.sendRequest(getDocumentRequest);
index++;
documentLength--;
}
So I'm trying to make the first Request(listDocumentsRequest) then wait till I got an answer, then run the second request (getDocumentRequest) ,wait till I got an answer then move to the next iteration.
Do you guys have any idea?
Best Regards
Edited after Chilly answer
while(documentLength>0)
{
const interval = setTimeout(() => {}, Number.MAX_SAFE_INTEGER);
function resolvedPromise() {
return new Promise((resolve, reject) => {
pm.sendRequest(listDocumentsRequest, (err, res) => {
if (err) {
console.log(err);
reject();
} else {
pm.environment.set('dossierId',res.json().documentsList[index].subDossierId)
pm.environment.set('documentId',res.json().documentsList[index].documentId)
resolve();
}
});
});
}
resolvedPromise()
.then(pm.request(getDocumentRequest))
.then(() => clearTimeout(interval))
.catch(err => {
console.log(err);
clearTimeout(interval);
});
index++;
documentLength--;
}
// Example with a plain string URL
pm.sendRequest('https://postman-echo.com/get', (error, response) => {
if (error) {
console.log(error);
} else {
// Example with a plain string URL
pm.sendRequest('https://postman-echo.com/get/1', (error, response) => {
if (error) {
console.log(error);
} else {
console.log(response);
}
});
}
});
You can simply chain the requests what is the error you are facing? in your case it looks like
while (documentLength > 0) {
pm.sendRequest(listDocumentsRequest, function (err, res) {
pm.environment.set('dossierId', res.json().documentsList[index].subDossierId)
pm.environment.set('documentId', res.json().documentsList[index].documentId)
pm.sendRequest(getDocumentRequest, function (err, res) {});
index++;
documentLength--;
});
}
Related
I'm trying to wait for a forEach to finish, and the forEach loop has two nested requests inside.
I need to wait untill the forEach finish beacuse I fill an array with the queries results and then, when the forEach is finish, then call another function, but I cannot do it well because sometimes, the array is fully filled, but othertimes the array is incomplete.
Here is my code:
readAllClientsAndInvoices: function(request, response) {
let clientsInvoices = [];
DAOClients.readAllClientesById(request.session.id, function (err, clients) {
if (err) {
console.log(err);
} else {
clients.forEach(function (client, idx, array) {
DAOClients.readClientDataById(client.id, function (err, data) {
if (err) {
console.log(err)
} else {
DAOClients.readAllclientInvoices(data.id, function (err, invoices) {
if (err) {
console.log(err);
} else {
let pair = {
clientData: data,
invoicesList: invoices
};
clientsInvoices.push(pair);
}
});
}
if (idx === array.length - 1) {
DAOClients.createClientPDFReportWOCommentsV2(clientsInvoices, function (err, res) {
if (err) {
console.log(err);
} else {
response.redirect(307, '/client/searchClient');
}
});
}
});
});
}
});
}
This is how I do it now, but I need to wait untill the array is fully filled with all the clients and its invoices and then call to createclientPDFReportWOCommentsV2 function but I don't know how to do it.
Thanks everyone
You can try to use a map instead of forEach in order to accept a return value from every call of the callback function, that return value will have to be a Promise, resolving after particular call has been completed. Since I don't see any particular error handling in your example I just made it so that in case of error Promise resolves undefined which is filtered afterwards in the createClientPDFReportWOCommentsV2 call.
function readAllClientsAndInvoices(request, response) {
DAOClients.readAllClientesById(request.session.id, function (err, clients) {
if (err) return console.log(err);
Promise.all(clients.map(client => {
return new Promise(resolve => {
DAOClients.readClientDataById(client.id, function (err, data) {
if (err) {
console.log(err)
resolve();
} else {
DAOClients.readAllclientInvoices(data.id, function (err, invoices) {
if (err) {
console.log(err);
resolve();
} else {
let pair = {
clientData: data,
invoicesList: invoices
};
resolve(pair);
}
});
}
});
});
})).then(clientsInvoices => {
DAOClients.createClientPDFReportWOCommentsV2(clientsInvoices.filter(Boolean), function (err, res) {
if (err) {
console.log(err);
} else {
response.redirect(307, '/client/searchClient');
}
});
});
});
}
To solve these problems i would use Async/Await https://javascript.info/async-await. Make sure all the methods you're calling on DAOClients returns a Promise https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
For example
function readAllClientesById() {
return new Promise((resolve, reject) => {
// Wait for some data to get fetched from SQL
// and call resolve instead of callback function
resolve(data)
// Or of there was an error
reject(err)
})
}
This is natively supported in the latest versions of Node.js.
Example of Async/Await if promises is implemented:
async function readAllClientsAndInvoices(req, res) {
try {
const clientInvoices = []
const clients = await DAOClients.readAllClientesById(req.session.id)
for (const client of clients) {
const clientData = await DAOClients.readClientDataById(client.id)
const clientInvoices = await DAOClients.readAllclientInvoices(clientData.id)
clientInvoices.push({
clientData: data,
invoicesList: invoices
})
}
// This code won't be executed until the for loop is completed
await DAOClients.createClientPDFReportWOCommentsV2(clientInvoices)
} catch (err) {
return res.status(err.code).send(err)
}
res.redirect(307, '/client/searchClient');
}
I haven't tested the code, it's just an example of how I approach these type of problems.
This is a superagent call, I have imported request(i.e is exported from my superagent component class)
How do I use async/await in this for "res.resImpVariable".
request
.post(my api call)
.send(params) // an object of parameters that is to be sent to api
.end((err, res) => {
if(!err) {
let impVariable = res.resImpVariable;
} else {
console.log('error present');
}
});
I reformulated my answer. I think I was misinterpreting before. You could wrap the entire sequence into a Promise-returning function that resolves after the response callback:
function callSuperagent() {
return new Promise((resolve, reject) => {
return request
.post(my api call)
.send(params) // an object of parameters that is to be sent to api
.end((err, res) => {
if(!err) {
console.log('get response', res);
// uncomment this to see the catch block work
// reject('Bonus error.');
resolve(res);
} else {
console.log('error present', err);
reject(err);
}
});
});
}
Then, you can create an async function and await that:
async function doSomething() {
try {
const res = await callSuperagent();
// uncomment this to see the catch block work
// throw 'Artificial error.';
console.log('res', res);
console.log('and our friend:', res.resImpVariable);
} catch (error) {
throw new Error(`Problem doing something: ${error}.`);
}
}
doSomething();
Or if you don't make doSomething, it would be like this:
callSuperagent()
.then((res) => {
console.log('res', res);
console.log('and our friend:', res.resImpVariable);
})
.catch((err) => {
console.log('err', err);
})
i'm trying to get some data from MSSQL using Node.js and then pass the data from node to my HTML layout (EJS), but i'm facing some a problem in the last part, this is what i'm trying to do:
app.js file:
app.get('/', (req, res) => {
var data = getJson(); // Function that return my data
res.render(__dirname + '/index.ejs', {
data: data
}, (err, file) => {
if (err) console.log(err);
res.send(file);
});
});
Function (also in the same file):
function getJson(config) {
sql.connect(config, err => {
if (err) return err;
var request = new sql.Request();
request.query('select * from data', (err, json) => {
if (err) return err;
var result = JSON.stringify(json); // I tried to stringfy this, but doesn't work neither
console.log(result); // This console inside of the function works!
return result;
});
});
return result;
};
Then when I load the page I get the result "undefined".
But if I pass just a simple variable through the app.get, it works!:
app.get('/', (req, res) => {
var data = 'data'; // Simple variable
res.render(__dirname + '/index.ejs', {
data: data // It works!!!
}, (err, file) => {
if (err) console.log(err);
res.send(file);
});
});
Then I tried to make a simple function and see if the result can be showed, an it does!:
function getJson() {
var data = 'data'; // It works too!!!
return data;
};
So I don't know what i'm doing wrong anymore, can any of you guys help me?
You're sending your data before await for them...
You should learn what is async function...
Look at this next code :
function getJson(config) {
return new Promise((resolve, reject) => {
sql.connect(config, err => {
if (err) return resolve(err);
var request = new sql.Request();
request.query('select * from data', (err, json) => {
if (err) return reject(error);
var result = JSON.stringify(json); // I tried to stringfy this, but doesn't work neither
console.log(result); // This console inside of the function works!
resolve(result);
});
});
})
};
app.get('/', (req, res) => {
getJson()
.then(data => {
res.render(__dirname + '/index.ejs', {
data: data
}, (err, file) => {
if (err) console.log(err);
res.send(file);
});
})
.catch(error => { /* do something */ });
});
Your getJson is doing an async operation. That is why you pass a callback to sql.connect and another to request.query.
It is like this. When you call getJson, the sql.connect function is executed, and the rest of the function continues running (return result;). That is why you get undefined.
i am trying to perform a simple action like upload a file to dropbox,
the file is upload succsfully
what i need is the returned answer that conatain file name,size,path etc.
i know that i lost in the async calls,
and i would like to get some help here please:
exports.uploadFile = async function () {
fs.readFile('./text.txt', function (err, contents) {
if (err) {
console.log('Error: ', err);
}
uploadFile(contents);
});
} ;
async function uploadFile(fileCont) {
let dbx = new Dropbox({ accessToken: APP_KEY });
await dbx.filesUpload({ path: '/basic4.txt', contents: fileCont })
.then(function (response) {
console.log( response);
return response;
})
.catch(function (err) {
console.log(err);
});
}
and i wanted to return the result to fron and so i used this part:
DriveService.uploadFile()
.then((success)=>{
return res.status(200).json({success:true,data:success,message:'list of files recived'});
})
.catch((error)=>{
return res.status(400).json({success:false,data:{},message:error.message});
})
the problem is that the success is always empty since i got lost in the async forest.
can somone please advise?
Thanks
Not sure bout solution in async but, You can use callback like this:
exports.uploadFile = async function (cb) {
fs.readFile('./text.txt', function (err, contents) {
if (err) {
console.log('Error: ', err);
}
uploadFile(contents,cb);
});
} ;
async function uploadFile(fileCont,cb) {
let dbx = new Dropbox({ accessToken: APP_KEY });
await dbx.filesUpload({ path: '/basic4.txt', contents: fileCont })
.then(function (response) {
console.log( response);
cb(response);//Pass response in callback
})
.catch(function (err) {
console.log(err);
});
}
DriveService.uploadFile(function(success) {//this callback will be called from async
return res.status(200).json({success:true,data:success,message:'list of files recived')
})
.catch((error)=>{
return res.status(400).json({success:false,data:{},message:error.message});
})
I use the following code and in the before I copy files that the tests after are using assertion but when I run it the before/each is happen after the test, what am I missing here?
I tried also with beforeach without success
describe(" Handler", function() {
before((done) => {
fs.stat(utils.pathSetup() + "/ins/", function (err, stats) {
if (!err) {
console.log("success");
} else {
let lclpath = utils.pathSetup();
Loder.add({folderPath: lclpath + "/test/testcontent/ins"});
console.log(err);
}
});
done();
});
//This are called before the previous statement why????????
//This should happen after the before has finished,they are in the same test block and this called is right after...
Handler.invoke(req, res)
.then((Ref) => {
}).done();
ee.on('Started', (arg) => {
evtResStart = arg;
});
in debug when I put BP it stops in before and click on step into take me to the Handler.invoke instead of inside the before...:(
Any idea what could be the reason for such thing?
If you are using done in your tests/befores, you need to call done() inside your callbacks, e.g.
before((done) => {
fs.stat(utils.pathSetup() + "/ins/", function (err, stats) {
if (!err) {
console.log("success");
} else {
let lclpath = utils.pathSetup();
Loder.add({folderPath: lclpath + "/test/testcontent/ins"});
console.log(err);
}
done();
});
});
Edit: Assuming the comments in your question are supposed to be formatted as code, is your Handler stuff in at it block?
it('should do something', () => {
Handler.invoke(req, res)
.then((Ref) => {
}).done();
ee.on('Started', (arg) => {
evtResStart = arg;
});
});
Have you tried putting done(); inside the callback of fs.stat?
In this way your tests should run as you want
before((done) => {
fs.stat(utils.pathSetup() + "/ins/", function (err, stats) {
if (!err) {
console.log("success");
} else {
let lclpath = utils.pathSetup();
Loder.add({folderPath: lclpath + "/test/testcontent/ins"});
console.log(err);
}
done();
});
});