I don't understand how the console.logs not getting printed.
import { GenericRepository, getGenericRepository } from '../src/database/repository/GenericRepository';
import { start, stop } from '../src/index';
import request from 'request';
const baseUrl = 'http://localhost:3200/';
const getTable = async (tableName: string) => {
const data = {
'tableName': 'tableName'
};
const header = {
url: baseUrl + 'table',
method: 'POST',
json: true
};
console.log('hello');
request.post({
url: 'http://localhost:3200/getTable',
body: data,
json: true
}, (error, response, body) => {
console.log('getting angry');
if (error) {
console.error('error: ', error);
} else {
console.log(response);
}
});
await new Promise((resolve, reject) => {
request.post({
url: 'http://localhost:3200/getTable',
json: data
}, (error, response, body) => {
console.log('getting angry');
if (error) {
console.error('error: ', error);
reject(error);
} else {
console.log(response);
resolve('response' + response);
}
});
})
}
describe('A suite', function () {
beforeAll(async done => {
// await start()f.catch(error => { console.log(error); });
done();
});
afterAll(() => {
console.log('afterall')
});
it('contains spec with an expectation', async done => {
console.log('spec executed')
getTable('supply').then(result => {
console.log('result: ', result)
}).catch(error => {
console.log('error', error);
});
console.log('after getTable')
done();
// expect(table.length).toBeGreaterThan(0);
});
});
Neither of these are getting printed:
console.log('getting angry');
console.error('error: ', error);
console.log(response);
console.log('result: ', result);
console.log('result: ', result);
console.log(response);
what actually gets printed is:
Started
spec executed
hello
after getTable
.afterall
Please help me understand what's going on!.
I tested it with postman the server is working properly.
I would expect that the request would return the same result as the postman does.
it('contains spec with an expectation', async done => {
console.log('spec executed')
getTable('supply').then(result => {
console.log('result: ', result)
}).catch(error => {
console.log('error', error);
});
console.log('after getTable')
done();
// expect(table.length).toBeGreaterThan(0);
});
This code says to synchronously do all of the following: Call getTable, which returns a promise. Then schedule some stuff to be done when (if) that promise resolves. Then call done(), thus ending the test. Since the test has been ended, the async stuff in getTable doesn't happen, nor do the .then callbacks.
Instead, you need to wait until getTable's promise is done resolving before you finish the test. Also, since you're already in an async function, you don't need to be using .then callbacks, and don't need to use done() since jasmine knows to wait until the async function's promise finishes. For example:
it('contains spec with an expectation', async () => {
console.log('spec executed')
try {
const result = await getTable('supply')
console.log('result: ', result)
} catch (error) {
console.log('error', error);
}
console.log('after getTable')
});
You're almost there, but your call to done() is not in the right place. The test will run, launch the Promise and then immediately notify that it is done() before the promise has chance to resolve or reject.
Try moving the done() to within the then and catch blocks:
it('contains spec with an expectation', async done => {
getTable('supply').then(result => {
console.log('result: ', result)
done()
}).catch(error => {
console.log('error', error)
done.fail(error)
});
});
Related
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 am trying to create a basic API in nodejs to perform CRUD actions on a database.
I do not understand why the result is undefined
exports.getPlaylist = async function (req, res) {
console.log('Recieved getPlaylist request');
result = await connection.executeQuery('SELECT * from Users');
res.status(200).send(result);
console.log(result); // Logs undefined
};
This is the function that gets called and gets the data from the database:
async executeQuery(query) {
connection.query(query, function (err, result) {
if (err) {
console.log('Error executing query: ' + err);
}
console.log(result); // logs correct data
return result;
});
}
You need to "promisify" your callback. (see require('utils').promisify ) for a shorthand for applying to functions that follow node.js callback style (function(err,result){}).
executeQuery(query) {
return new Promise((res, rej) => {
connection.query(query, function (err, result) {
if (err) {
console.log('Error executing query: ' + err);
rej(err)
} else {
console.log(result); // logs correct data
res(result);
}
});
});
}
Now inside an async function you can await executeQuery(query)
The execute is not a promise base function, you cannot use await on a callback function.
change the execute function to promise base
Example:
executeQuery(query) {
return new Promise( (resolve, reject) => {
connection.query(query, function (err, result) {
if (err) {
console.log('Error executing query: ' + err);
reject('Error executing query: ' + err);
}
console.log(result); // logs correct data
resolve(result);
});
});
}
Add try catch in your calling function
exports.getPlaylist = async function (req, res) {
console.log('Recieved getPlaylist request');
try{
result = await connection.executeQuery('SELECT * from Users');
res.status(200).send(result);
console.log(result); // Logs undefined
} catch(error) {
console.log(error)
}
};
So I have a code as below. There is a function that calls 2 axios requests to fetch some sample API data.
function fetch_records(){
var api_url1 = "https://api.github.com/users/mojombo"
var api_url2 = "https://api.github.com/users/defunkt"
axios.get(api_url1)
.then(function (response) {
console.log('Data1 received: ',response);
})
.catch(function (error) {
console.log(error);
})
axios.get(api_url2)
.then(function (response) {
console.log('Data2 received: ',response);
})
.catch(function (error) {
console.log(error);
})
}
And then I want to run this function fetch_records() as below
console.log('Script started');
fetch_records();
console.log('Script ended');
So that the output should be
Script started
... api response data ...
Script ended
But because Javascript is asynchronous, it always gives output as below
Script started
Script ended
... api response data ...
I belive async/await or promise is used to achieve the response I want but I am not sure how to use that exactly.
Just use async/await keywords, but remember JS always is JS.
async function fetch_records() { // a async function
var api_url1 = "https://api.github.com/users/mojombo"
var api_url2 = "https://api.github.com/users/defunkt"
// waterfall way
const data1 = await axios.get(api_url1); // await
console.log('Data1 received: ', data1);
const data2 = await axios.get(api_url2); // await
console.log('Data2 received: ', data2);
// parallel way
// const [data1, data2] = await Promise.all([
// axios.get(api_url1),
// axios.get(api_url2)
// ]);
// console.log(data1, data2);
}
(async () => {
try {
console.log('Script started');
await fetch_records(); // await a async function (Thenable object)
console.log('Script ended');
} catch(err) {
console.error(err);
}
})();
change your function to return promises:
function fetch_records() {
var api_url1 = "https://api.github.com/users/mojombo"
var api_url2 = "https://api.github.com/users/defunkt"
const promise1 = axios.get(api_url1)
.then(function (response) {
console.log('Data1 received: ',response);
})
.catch(function (error) {
console.log(error);
})
const promise2 = axios.get(api_url2)
.then(function (response) {
console.log('Data2 received: ',response);
})
.catch(function (error) {
console.log(error);
});
return [promise1, promise2];
}
now use promise.all :
Promise.all(fetch_records()).then(function(response) {
console.log(response[0], response[1]);
});
function fetch_records() {
var api_url1 = "https://api.github.com/users/mojombo"
var api_url2 = "https://api.github.com/users/defunkt"
return [
axios.get(api_url1),
axios.get(api_url2)
]
}
console.log('Script started');
Promise.all(fetch_records()).then(res => {
console.log(res);
console.log('Script ended');
})
Promise.all will wait till all promises are resolved, more about it
function fetch_records() {
var api_url1 = "https://api.github.com/users/mojombo";
return new Promise((resolve, reject) => {
axios
.get(api_url1)
.then(function(response) {
console.log("Data1 received: ", response);
resolve(response);
})
.catch(function(error) {
console.log(error);
reject(error);
});
});
}
Use with Async/Await :
async function getData() {
let data = await fetch_records();
console.log("Fetch Records :: ", data);
}
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 have the following test case:
it("should pass the test", async function (done) {
await asyncFunction();
true.should.eq(true);
done();
});
Running it asserts:
Error: Resolution method is overspecified. Specify a callback or
return a Promise; not both.
And if I remove the done(); statement, it asserts:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure
"done()" is called; if returning a Promise, ensure it resolves.
How to solve this paradox?
You need to remove the done parameter as well, not just the call to it. Testing frameworks like Mocha look at the function's parameter list (or at least its arity) to know whether you're using done or similar.
Using Mocha 3.5.3, this works for me (had to change true.should.be(true) to assert.ok(true) as the former threw an error):
const assert = require('assert');
function asyncFunction() {
return new Promise(resolve => {
setTimeout(resolve, 10);
});
}
describe('Container', function() {
describe('Foo', function() {
it("should pass the test", async function () {
await asyncFunction();
assert.ok(true);
});
});
});
But if I add done:
describe('Container', function() {
describe('Foo', function() {
it("should pass the test", async function (done) { // <==== Here
await asyncFunction();
assert.ok(true);
});
});
});
...then I get
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
Removing done as a param from it worked for me! Instead only use expect/should. Example is as follows:
getResponse(unitData, function callBack(unit, error, data){ try {
return request.post(unit, function (err, resp) {
if (!err && resp.statusCode === 200) {
if (resp.body.error) {
return callback(obj, JSON.stringify(resp.body.error), null);
}
return callback(obj, null, resp);
} else {
if (err == null) {
err = { statusCode: resp.statusCode, error: 'Error occured.' };
}
return callback(obj, err, null);
}
});
} catch (err) {
return callback(obj, err, null);
}}
BEFORE:
it('receives successful response', async (done) => {
const getSomeData = await getResponse(unitData, function callBack(unit, error, data){
expect(data.statusCode).to.be.equal(200);
done();
}) })
AFTER (works):
it('receives successful response', async () => {
const getSomeData = await getResponse(unitData, function callBack(unit, error, data){
expect(data.statusCode).to.be.equal(200);
}) })
Sometimes there are cases you need to use async/await + done function in mocha.
For example, in one of my socket.io unit test cases, I have to call db functions with async functions and test socket event handlers which are callback functions:
context("on INIT_CHAT", ()=> {
it("should create a room", async (done) => {
const user = await factory.create("User");
socket.emit("INIT_CHAT", user);
socket.on("JOIN_CHAT", async (roomId) => {
const room = await ChatRoom.findByPk(roomId);
expect(room).to.exist;
// then I need to close a test case here
done();
});
});
});
This will causes the exact same error as in the OP:
Error: Resolution method is overspecified. Specify a callback or return a Promise; not both.
My Workaround:
I just wrapped the entire test code in a promise generator:
context("on INIT_CHAT", ()=> {
it("should create a room", async () => {
const asyncWrapper = () => {
return new Promise(async (resolve) => {
const user = await factory.create("User");
socket.emit("INIT_CHAT", user);
socket.on("JOIN_CHAT", async (roomId) => {
const room = await ChatRoom.findByPk(roomId);
expect(room).to.exist;
resolve(true);
});
});
});
await asyncWrapper();
});
});