js I just create a 2 function to send the response var = y but unfortunately res.end() work before then my y works..
This code work well with for loop without mine query but when i used a query it working stop and it gives res like below. Before promise call. Loop completed. Promise resolved: 0 Next step. 13289, 2170, 2165, 2146, 2115, 2138, 2143, 2112, 1964, 2685, 6945, 2687, 2688, 2902, 2935, 2941, 3094, 3095, 3164, 3096,
var http = require('http');
var url = require('url');
var fs = require('fs');
var mysql = require('mysql');
http.createServer(function (req, res) {
var q = url.parse(req.url, true);
var end = '';
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "justcode"
});
//1. Create a new function that returns a promise
function firstFunction() {
return new Promise((resolve, reject) => {
let arr = [];
con.connect(function (err) {
if (err) throw err;
con.query("SELECT * FROM wp_posts WHERE `post_type` = 'post'", async function (err, result, fields) {
if (err) throw err;
result.forEach(element => {
arr.push(element['ID']);
});
resolve(arr)
});
});
})
}
//2. Create an async function
async function secondFunction() {
//3. Await for the first function to complete
const result = await firstFunction()
res.end(JSON.stringify(result));
};
secondFunction()
}).listen(8080);
This is the working code::::
CodePudding user response:
How about this...
//1. Create a new function that returns a promise
function firstFunction() {
return new Promise((resolve, reject) => {
let y = 0
con.connect(function (err) {
if (err) throw err;
con.query("SELECT * FROM wp_posts WHERE `post_type` = 'post'", async function (err, result, fields) {
if (err) throw err;
result.forEach(element => {
console.log(element['ID']);
y ;
});
// get the results from post table
console.log('Loop completed.')
resolve(y); // <---- Resolve the promise here
});
});
// for (i = 0; i < 100; i ) {
// y
// }
// console.log('Loop completed.')
// resolve(y) // <--- Moving this inside con.query callback
})
}
//2. Create an async function,
async function secondFunction() {
console.log('Before promise call.')
//3. Await for the first function to complete
const result = await firstFunction()
console.log('Promise resolved: ' result)
console.log('Next step.')
res.end();
};
secondFunction()
Problem in The Original Question
con.query is an asynchronous execution. It accepts a callback function which then it invokes once the operation has completed. javascript has something called runToCompletion in which the execution of a function continues until the last statement.
When secondFunction is invoked, it further invokes(with an await) firstFunction which returns a Promise and the execution of the promise starts, but the caller secondFunction is waiting for the promise to finish.
Inside the execution of the Promise of firstFunction, there is a call to con.query, which is an asynchronous call, but isn't being waited for. Hence, after invoking the call to con.query, the javascript execution continues further... only to encounter a resolve after a couple of statements. A resolve finishes the execution of the Promise of firstFunction and control passes back to secondFunction and then execution continues from there on. Now, since the call to con.query will finish after sometime, and when it does, the callback function will be executed. And so we are seeing the behavior as problematic. But it's all happening as per the semantics of javascript execution.
CodePudding user response:
Assume you are using mysql, since it does not provide a promise API out of the box, you may need to promisify the connect() call and query() call yourself and await for them.
async function firstFunction() {
let y = 0;
await new Promise((resolve,reject)=>{
con.connect(function (err) {
if (err) reject(err);
resolve();
});
});
let result = await new Promise((resolve,reject)=>{
con.query("SELECT * FROM wp_posts WHERE `post_type` = 'post'", (err, result, fields) => {
if (err) reject(err);
resolve(result);
// get the results from post table
});
});
result.forEach(element => {
console.log(element['ID']);
y ;
});
// for (i = 0; i < 100; i ) {
// y
// }
console.log('Loop completed.')
return y;
}
Alternatively, you may try using wrapper library like mysql-promise and promise-mysql
