I am using Knex migrations with regular promise methods, like this:
exports.up = function (knex) {
return knex.schema
.hasTable('table_name')
.then(function (exists) {
if (!exists) {
return knex
.schema
.createTable('table_name', function (table) {
table.increments('id').primary();
})
.then(console.log('created table_nametable'));
}
});
};
How would I refactor this to use async/await? The overall structure, where we are returning knex.schema with a chain of promise methods is throwing me for a loop.
something like this should do:
exports.up = async function (knex) {
if (! (await knex.schema.hasTable('table_name')) ) {
await knex.schema.createTable('table_name', function (table) {
table.increments('id').primary();
});
}
// awaiting sequentially multiple promises to resolve one by one
for (let item of arrayOfStuffToAwait) {
await item;
}
}
exports.down = async function (knex) {
await knex.schema.dropTable('table_name');
}
Related
I'm querying a mariadb using a class i wrote, my code works when i use console.log but not when i use a return statement:
class DBinteractor{
//constructor of my class
constructor(){
this.mariadb = require('mariadb');
this.pool = this.mariadb.createPool({
socketPath: '/run/mysql/mysql.sock',
user: 'me_user',
password: 'me_password',
database: 'me_database',
connectionLimit: 5
});
}
//asyncronous method
async asyncQuery(){
var quest = "SELECT DISTINCT `Modalite1` FROM `synth_globale` WHERE 1;";
try {
this.conn = await this.pool.getConnection();
const rows = await this.conn.query(quest);
this.conn.end();
return rows;
}
catch (err) {
throw err;
}
finally {
}
}
// I need at some point a method able to return the result of my query
// to put it in a variable and use it outside:
syncQuery(){
// as is, a non-async function/method can not include async calls
// I must use an iife to be able to do it
(async () => {
let ResultOfQueryWithinMethod = (await this.asyncQuery());
console.log(ResultOfQueryWithinMethod);
//OK, my result query is rightfully printed on the console
return(ResultOfQueryWithinMethod);
})()
}
}
queryator = new DBinteractor();
let ResultOfQueryOutsideMethod = queryator.syncQuery();
console.log(ResultOfQueryOutsideMethod);
//NOT OK, ResultOfQueryOutsideMethod is undefined
It's just like the return statement in syncQuery doesn't make the link between ResultOfQueryWithinMethod and ResultOfQueryOutsideMethod
What am i missing ?
thanks for your help
I'm new to next js. And I have one user.js file inside of my pages directory in next.js. This is the source code:
// pages/user.js
function user(props) {
const [userList, setUserList] = useState([])
const [roleList, setRoleList] = useState([])
async function initialFetch() {
const userList = await fetch('GET', GET_ALL_USERS)
setUserList(userList)
const roleList = await fetch('GET', GET_ALL_ROLES)
setRoleList(roleList)
console.log('userList in async')
console.log(userList)
}
if (!props.userList.status) {
initialFetch()
} else {
setUserList(props.userList)
setRoleList(props.roleList)
}
console.log('userList outside')
console.log(userList)
return (
<>
<TableUserManagement users={userList} roles={roleList}/>
</>
)
};
user.getInitialProps = async (ctx) => {
const userList = await fetch('GET', GET_ALL_USERS)
const roleList = await fetch('GET', GET_ALL_ROLES)
return {userList, roleList}
}
The problem is that above async initialFetch() function is always called uninfinitively :
So what am I doing wrong here? Thank you
Note: I have tried to use useEffect() but the looping still happening. This the code :
useEffect(
() => {
if (!props.userList.status) {
initialFetch()
} else {
setUserList(props.userList)
setRoleList(props.roleList)
}
console.log('user list diliuar')
console.log(userList)
}
)
This issue is not related to Next.js but React itself. This is the code that cause unfinite calls:
if (!props.userList.status) {
initialFetch()
} else {
setUserList(props.userList)
setRoleList(props.roleList)
}
Since after setting any state, your component re-renders and that part of code keeps running again, and the fetch cause setting state again,... that loops forever.
You should move you data-fetching logic in side componentDidMount or useEffect. Remember to provide the dependency array of useEffect. In this case, you may only need to fetch data only once so you should provide the empty dependency array.
useEffect(() => {
async function initialFetch() {
const userList = await fetch('GET', GET_ALL_USERS)
setUserList(userList)
const roleList = await fetch('GET', GET_ALL_ROLES)
setRoleList(roleList)
}
if (!props.userList.status) {
initialFetch()
} else {
setUserList(props.userList)
setRoleList(props.roleList)
}
}, []);
P/s: you should name you React component in PascalCase (ex: User)
How can I use Knexjs to fetch data synchronously on a resolver in Apollo GraphQL Server? For instance, if I run the following query:
const resolvers = {
Query: {
MySchema: (_, args, { dataSources }, info) => {
var result = db.knex.select('*')
.from('SomeTable')
.where({SomeColumn:'SomeValue'})
.then(function(rows) {console.log(rows)})
.catch(function(error) {console.error(error)});
// Do something with the result here..
console.log(result);
return db.knex.select('*').from('SomeOtherTable')
}
}
}
The line console.log(result); just displays a Promise {<pending>} and by the time the line .then(function(rows) {console.log(rows)}) is executed (asynchronously), the main function will be already finished.
Is there a way to get the result of the database query instead of a Promise on line console.log(result);?
If you want your request to run synchronously and wait the result you need to add async/await
MySchema: async (_, args, { dataSources }, info) => {
var result = await db.knex.select('*')
.from('SomeTable')
.where({SomeColumn:'SomeValue'})
// result is now a value and not a promise
console.log(result)
}
As you noticed, I removed the .then and the .catch that are not relevant anylonger.
I highly recommend adding a try/catch around your awaited promise to avoid uncaught error.
MySchema: async (_, args, { dataSources }, info) => {
try {
var result = await db.knex.select('*')
.from('SomeTable')
.where({SomeColumn:'SomeValue'})
// result is now a value and not a promise
console.log(result)
} catch (e) {
// handle e
}
}
By the way, the return db.knex.select('*').from('SomeOtherTable') would benefit an await aswell to return data instead of a promise.
Trying to understand what is difference between these all with respect to axios library.
function doSomething() {
axios.get(url)
.then((response) => process(response))
.catch((error) => handle(error))
}
vs
async function doSomething() {
try {
const response = await axios.get(url);
process(response);
} catch(error) {
handle(error);
}
}
vs
async function doSomething() {
return await axios.get(url);
}
vs
function doSomething() {
return axios.get(url);
}
Trying to understands this and write wrapper for axios calls for the consumer.
Thanks.
I want to make the UserDataGenerator class works like a traditional SYNC class.
My expectation is that userData.outputStructure can give me the data prepared.
let userData = new UserDataGenerator(dslContent)
userData.outputStructure
getFieldDescribe(this.inputStructure.tableName, field) is a ASYNC call which invokes Axios.get
Below is my current progress but it's still not waiting for the data ready when I print out the userData.outputStructure
export default class UserDataGenerator {
inputStructure = null;
outputStructure = null;
fieldDescribeRecords = [];
constructor(dslContent) {
this.outputStructure = Object.assign({}, dslContent, initSections)
process()
}
async process() {
await this.processSectionList()
return this.outputStructure
}
async processSectionList() {
await this.inputStructure.sections.map(section => {
this.outputStructure.sections.push(this.processSection(section));
})
}
async processSection(section) {
let outputSection = {
name: null,
fields: []
}
let outputFields = await section.fields.map(async(inputField) => {
return await this._processField(inputField).catch(e => {
throw new SchemaError(e, this.inputStructure.tableName, inputField)
})
})
outputSection.fields.push(outputFields)
return outputSection
}
async _processField(field) {
let resp = await ai
switch (typeof field) {
case 'string':
let normalizedDescribe = getNormalizedFieldDescribe(resp.data)
return new FieldGenerator(normalizedDescribe, field).outputFieldStructure
}
}
You're trying to await arrays, which doesn't work as you expect. When dealing with arrays of promises, you still need to use Promise.all before you can await it - just like you cannot chain .then on the array.
So your methods should look like this:
async processSectionList() {
const sections = await Promise.all(this.inputStructure.sections.map(section =>
this.processSection(section)
));
this.outputStructure.sections.push(...sections);
}
async processSection(section) {
return {
name: null,
fields: [await Promise.all(section.fields.map(inputField =>
this._processField(inputField).catch(e => {
throw new SchemaError(e, this.inputStructure.tableName, inputField)
})
))]
};
}