Sequelize nodejs pass value to another function - javascript

Here is my function which return count fine.But I want its value to be used in my response.
var PostComment = require("../models/PostComment");
var getPostCount = function (postId,res) {
return PostComment.findAll({where: {post_id: postId}}).then(function (comments) {
return comments.length;
});
}
module.exports = {
getPostCount: getPostCount
}
Here is my another function. Console log working fine. But I need to return value.
arr.push({
id: item.id,
post_userid: item.post_userid,
post_sendername: item.post_sendername,
post_description: item.post_description,
attach_status: item.attach_status,
post_datetime: item.post_datetime,
post_status: item.post_status,
remove_id: item.remove_id,
attachment_list: item.tbl_post_attachments,
total_like:totalLikes,
comment_count:Samparq.getPostCount(item.id, res).then(function (commentCount) {
console.log(commentCount);
}),
comment_list:item.tbl_post_comments
});

SIDENOTE:
You can use the count method in your first code block:
var PostComment = require("../models/PostComment");
var getPostCount = function (postId) {
return PostComment.count({where: {post_id: postId}});
}
module.exports = {
getPostCount: getPostCount
}
In your second code block, you're getting a Promise back in comment_count, not an actual number.
You need to first get the count, then add it to the object.
Samparq.getPostCount(item.id).then(function (count) {
arr.push({
id: item.id,
post_userid: item.post_userid,
post_sendername: item.post_sendername,
post_description: item.post_description,
attach_status: item.attach_status,
post_datetime: item.post_datetime,
post_status: item.post_status,
remove_id: item.remove_id,
attachment_list: item.tbl_post_attachments,
total_like:totalLikes,
comment_count: count,
comment_list:item.tbl_post_comments
});
})
SIDENOTE #2:
If you use async await, which is new to node, you'll be able to make it look more like your original code. If you're inside an async function, then your second codeblock could look like this:
arr.push({
id: item.id,
post_userid: item.post_userid,
post_sendername: item.post_sendername,
post_description: item.post_description,
attach_status: item.attach_status,
post_datetime: item.post_datetime,
post_status: item.post_status,
remove_id: item.remove_id,
attachment_list: item.tbl_post_attachments,
total_like:totalLikes,
comment_count: await Samparq.getPostCount(item.id),
comment_list:item.tbl_post_comments
});

Related

Follow on actions after asynch function completion

I'm going to do my best to explain this one since this is a reduced version of the real code and some parts might seem redundant or excessive (and they might be). The model can be found at https://jsfiddle.net/ux5t7ykm/1/. I am using a function to build an array of values that are passed to another function to do a REST call for the data that corresponds to the values. The array lists the name of the list to get the data from, the field name, the filter field name, the filter value, and the target array to pass the autocomplete values back to. This part is working fine and is essentially what Step1() does. setAutocomplete() then uses getData() to make the multiple REST calls. I'm using sprLib for that part so it's already a promise (this is getListItems() normally). getData() is where the magic is happening. It recursively cycles through the list and performs getListItems() until all the data is retrieved. I have this set as an async function with await. This also seems to be running fine.
The problem I have is that once this whole sequence is complete, I then have another function that I need to run. It manipulates the data from the previous function. I've tried to put step1() in a promise, make it async, etc. Nothing seems to work. CheatStep() seems to be where a response or some other method signaling to Step1() should go to then allow the next function to run. I've been banging my head against this all week and I feel like my understanding of promises and asnyc is regressing.
var dict = [{
'id': '1',
'title': 'test1'
}, {
'id': '2',
'title': 'test2'
}, {
'id': '3',
'title': 'test3'
}, {
'id': '4',
'title': 'test4'
}, ]
step1()
nextStep()
function nextStep() {
console.log('I run after Step1')
}
function cheatStep() {
console.log('I cheated')
}
function step1() {
setAutoComplete(4);
}
function setAutoComplete(listIndex) {
getData(listIndex,
function(result) {
for (var i = 0; i < listIndex; i++) {
var autoDict = result[i];
console.log(autoDict)
}
cheatStep()
},
function(e) {
console.error(e);
alert('An error occurred wile setting autocomplete data for item');
})
}
async function getData(listIndex, success, error, curIndex, result) {
var curIndex = curIndex || 0;
var result = result || {};
await getListItems(curIndex,
function(listItems) {
result[curIndex] = listItems;
curIndex++;
if (listIndex > curIndex) {
getData(listIndex, success, error, curIndex, result);
console.log('1');
} else {
console.log('2');
success(result);
}
},
error)
}
function getListItems(curIndex, success, error) {
new Promise(
function(resolve, reject) {
var x = dict[curIndex];
resolve(x);
})
.then(function(x) {
success(x);
});
}
I have adopted your code to a more async/await view coz you still use heavily callback approach:
var dict = [{
'id': '1',
'title': 'test1'
}, {
'id': '2',
'title': 'test2'
}, {
'id': '3',
'title': 'test3'
}, {
'id': '4',
'title': 'test4'
}, ]
function nextStep(result) {
console.log('I run after Step1',result)
}
function cheatStep() {
console.log('I cheated')
}
step1().then((result)=>{nextStep(result)})
async function step1() {
return await setAutoComplete(4);
}
async function setAutoComplete(listIndex) {
const result = await getData(listIndex);
for (var i = 0; i < listIndex; i++) {
var autoDict = result[i];
console.log(autoDict)
}
cheatStep()
return result
}
async function getData(listIndex, curIndex=0, result={}) {
const listItems = await getListItems(curIndex)
result[curIndex] = listItems;
curIndex++;
if (listIndex > curIndex) {
return await getData(listIndex, curIndex, result);
} else {
console.log('2');
return (result);
}
}
function getListItems(curIndex) {
return new Promise(
(resolve, reject) =>{
resolve(dict[curIndex]);
})
}
I also kept recursion here, but personally I would prefer solution with a loop instead.
Also a minor advise. Try to avoid write declaration after usage:
nextStep()
function nextStep() {
console.log('I run after Step1')
}
JS hoisting does that a valid syntax but it is really hard to read=)

Javascript call function according to user input

I want to call a unique function according to the user's input on JavaScript. I'm working with Node.js, not HTML inputs. I'll leave an example code that explains my general code's goal. Is there any better approach than I did? What would you recommend to me? I don't want to add all the new functions to Map. I want to turn into dynamic too.
let functions = new Map([
["Annually", annually],
["Daily", daily],
["Weekly", weekly],
]);
async function choice() {
const answer = await inquirer.prompt({
name: "choice",
type: "list",
message: "How often do you want to get a notification?",
choices: ["Annually", "Daily", "Weekly"], //Gets choice from users think it's like a HTML form
});
functions.get(answer.choice)(); // Gets the function from map after that calls the function
}
async function annually() {
console.log("Annually works.");
}
async function weekly() {
console.log("Weekly works.");
}
async function daily() {
console.log("Daily works.");
}
i think this solution is better
const funcs = {
annually: async () => { // you can change "annually" to anything
console.log('Annually works.')
},
weekly: async () => {
console.log('Weekly works.')
},
daily: async () => {
console.log('Daily works.')
},
}
async function choice() {
const answer = await inquirer.prompt({
name: 'choice',
type: 'list',
message: 'How often do you want to get a notification?',
choices: Object.keys(funcs),
})
await funcs[answer.choice]()
}
The way you are accomplishing this seems like it would work, but I think there is a better way to do this that is more readable.
function handleDaily(){
console.log("daily works");
}
function handleWeekly(){
console.log("weekly works");
}
function handleAnnually(){
console.log("annually works");
}
var CHOICE_LIST = [];
const CHOICES = [
{value: "Daily", handle: handleDaily},
{value: "Weekly", handle: handleWeekly},
{value: "Annually", handle: handleAnnually},
];
//Builds choice list based off of CHOICES array
for(let i = 0; i < CHOICES.length; i++){
CHOICE_LIST.push(CHOICES[i].value);
}
function evalInput(input) {
for(let i = 0; i < CHOICES.length; i++){
if(input === CHOICES[i].value){
CHOICES[i].handle();
break;
}
}
}
async function getChoice(){
const answer = await inquirer.prompt({
name: "choice",
type: "list",
message: "How often do you want to get a notification?",
choices: CHOICE_LIST
});
evalInput(answer.choice);
}
No need to store the functions in a map unless you really need to. I also removed the async keyword from your functions that were not awaiting anything.
If these functions are in global object's scope you can do this:
var fn = answer.choice.toString();
if (global[fn] === "function") {
global[fn]();
}
If its in a module and you know the module exports
var someExports = require('./someExportsFile.js');
Object.keys(someExports)[fn];
PS:
If this was in browser, you could have used
var brFn = window[fn)];
if (typeof brFn === "function") brFn();

How would I be able to return more than one object based on user input amount

Let's say PackInput is an array input.
What I'd like to do's return a dynamic amount of objects depending on how large the input array PackInput is.
For example: if PackInput is [4,5,6], then I'd like three objects returned for each ItemID.
For example: return {... ItemID: 4 ...}, return {... ItemID: 5 ...}, return {... ItemID: 6 ...}.
My current code below is only grabbing the first item of the array instead of all of them and I'm not sure why. I've turned my wheels on this for so long and now I've hit a wall. What am I doing wrong?
for(let i = 0; i < PackInput.length; i++) {
return {
TimestampUTC: Date.now(),
Payload: {
ItemID : PackInput[i]
}
}
}
Updated:
let array = PackInput.map((items) => ({
TimestampUTC: Date.now(),
Payload: {
ItemID : items
}
})
);
let objects = array.reduce(function(target, key, index) {
target[index] = key;
return target;
})
return objects;
You can use the map method to achieve what you want
return PackInput.map((element) => ({
TimestampUTC: Date.now(),
Payload: {
ItemID : element
}
}))
A return statement ends the execution of a function, and returns control to the calling function/upper scope.
Update on object:
const object = PackInput.reduce(function(previousValue, currentValue, index) {
return {
...previousValue,
[index]: currentValue
}
}, {})
You need to provide an empty object as 2nd argument for the reduce function.
You can return an array/object. The problem is that you can call return only once in a function and as soon as a function reaches return it would be returned to the caller scope. You can use the loop to create the array/object and then return the final value:
let array = [];
for(let i = 0; i < PackInput.length; i++) {
array.push({
TimestampUTC: Date.now(),
Payload: {
ItemID : PackInput[i]
}
});
}
return array;

One array of object pulls data while other doesn't

So I have the following array of objects as shown below:
const default_apps = [
{
'post_title': 'Excel',
}, {
'post_title': 'Word',
}, {
'post_title': 'SharePoint',
}];
console.log(default_apps);
const test = get_array_of_post_objects('application_launcher');
console.log(test);
Here is the console log for both, the top is default_apps and the bottom is test:
Please note: Both array of objects have post_title: "..." defined inside.
Could someone tell me when I call my vue app using the default_apps array of objects, I get a return as shown below:
But if I substitute default_apps.map for test.map, I get an empty array back as shown here:
They're both very similar array of objects, so I'm just a little confused - All help would be appreciated!
new Vue({
name: 'o365-edit-modal-wrapper',
el: '#o365-modal-edit-wrapper',
data: function() {
return {
available_list: [],
selected_list: default_apps.map((name, index) => {
return {
name: name.post_title,
order: index + 1,
fixed: false
};
}),
editable: true,
isDragging: false,
delayedDragging: false,
}
},
});
Here is the get_array_of_objects function if anyone wants to check it out:
function get_array_of_post_objects(slug)
{
let items = [];
wp.api.loadPromise.done(function () {
const Posts = wp.api.models.Post.extend({
url: wpApiSettings.root + 'menus/v1/locations/' + slug,
});
const all_posts = new Posts();
all_posts.fetch().then((posts) => {
items.push(...posts.items);
});
});
return items;
}
get_array_of_post_objects function call is asynchronous call when executed it returns items which is an empty array and then when promise is resolved, no where to return it again, so you need to wait for the promise (resolved) to return the items.

Javascript function to return Elasticsearch results

I'm trying to write a JavaScript function that returns results of an Elasticsearch v5 query. I can't figure out where and how to include 'return' in this code. With the following, segmentSearch(id) returns a Promise object,{_45: 0, _81: 0, _65: null, _54: null}.
_65 holds an array of the correct hits, but I can't figure out how to parse it. The console.log(hits) produces that same array, but how can I return it from the function?
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'localhost:9200',
log: 'trace'
});
segmentSearch = function(id){
var searchParams = {
index: 'myIndex',
type: 'segment',
body: {
query: {
nested : {
path : "properties",
query : {
match : {"properties.source" : id }
},
inner_hits : {}
}
}
}
}
return client.search(searchParams).then(function (resp) {
var hits = resp.hits.hits;
console.log('hits: ',hits)
return hits;
}, function (err) {
console.trace(err.message);
});
}
I would instanitate a new array outside of your client.search function in global scope and array.push your 'hits' Then access your newly filled array.
let newArr = [];
client.search(searchParams).then(function (resp) {
for(let i = 0; i < resp.hits.hits.length; i++){
newArr.push(resp.hits.hits[i]);
}
console.log('hits: ',newArr)
return newArr;
}, function (err) {
console.trace(err.message);
});
First of all, elasticsearch js client is working with Promise ( I think using callback is also possible).
Using Promise is a good way to handle asynchronous computation.
In your question, you have already done something with a promise:
var search = function(id)
{
var searchParams = { /** What your search is **/}
return client.search(searchParams)
}
This call is returning a Promise.
If we consider handleResponse as the function in your then
var handleResponse = function(resp)
{
var hits = resp.hits.hits;
console.log('hits: ',hits)
return hits; //You could send back result here if using node
}
In your code, handleResponse is called once the promise is fullfield. And in that code you are processing data. Don't forget you are in asynchronious, you need to keep working with promise to handle hits.
By the way, in your question, what you have done by using "then" is chaining Promise. It is normal to have Promise.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
Promise.prototype.then is returning a Promise.
var segmentSearch = function ( id )
{
return search
.then( handleResponse //here you got your hit )
.then( function ( hits )
{
console.log(hits) //and here you have done something with hits from search.
})
}
I neglected to post my fix, sorry about that. The sequence is to create searchParams, perform client.search(searchParams) which returns a Promise of hits, then process those hits:
segmentSearch = function(obj){
// retrieve all segments associated with a place,
// populate results <div>
let html = ''
var plKeys = Object.keys(obj)
var relevantProjects = []
for(let i = 0; i < plKeys.length; i++){
relevantProjects.push(obj[plKeys[i]][0])
var searchParams = {
index: 'myIndex',
type: 'segment',
body: {
query: {
nested : {
path : "properties",
query : {
match : {"properties.source" : id }
},
inner_hits : {}
}
}
}
}
client.search(searchParams).then(function (resp) {
return Promise.all(resp.hits.hits)
}).then(function(hitsArray){
...write html to a <div> using hits results
}
}

Categories

Resources