I'm trying to fetch the data from my localhost Node server but I still getting this "JSON.parse: unexpected character at line 1 column 1 of the JSON data". It works fine when I fetch from https://randomuser.me/api/?results=10, but not for my own JSON array.
server.js (backend)
//RENDER HTML PAGE TO GET THE RESULTS
app.get('/device', isLoggedIn, function(req,res)
{
fs.readFile('./public/list.html', 'utf8', (err, data)=> {
res.write(data);
res.end();
});
});
//GENERATE MY JSON ARRAY
app.get('/mydevices', isLoggedIn, function(req,res)
{
connection.query("\
SELECT `dispositivos`.`nome` \
FROM `dispositivos` JOIN `usuarios` \
ON `usuarios`.`id` = `dispositivos`.`user_id` AND `user_id`='" + req.user.id + "'", (err,result)=>
{
res.json({'results': result});
// console.log(result)
});
});
controller.js (frontend - NOT working for my JSON)
window.onload = function(){
function createNode(element) {
return document.createElement(element);
}
function append(parent, el) {
return parent.appendChild(el);
}
const ul = document.getElementById('mydevices');
const url = 'http://localhost:777/mydevices';
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
let devices = data.results;
return devices.map(function(device) {
let li = createNode('li'),
// img = createNode('img'),
span = createNode('span');
// img.src = device.picture.medium;
span.innerHTML = `${device.nome}`;
// append(li, img);
append(li, span);
append(ul, li);
})
})
.catch(function(error) {
console.log(error);
});
};
controller.js (frontend - WORKING for randomuser.me API)
window.onload = function(){
function createNode(element) {
return document.createElement(element);
}
function append(parent, el) {
return parent.appendChild(el);
}
const ul = document.getElementById('authors');
const url = 'https://randomuser.me/api/?results=10';
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
let authors = data.results;
return authors.map(function(author) {
let li = createNode('li'),
img = createNode('img'),
span = createNode('span');
img.src = author.picture.medium;
span.innerHTML = `${author.name.first} ${author.name.last}`;
append(li, img);
append(li, span);
append(ul, li);
})
})
.catch(function(error) {
console.log(error);
});
};
In the rendered html I have id="devices" (of course I change it to "authors" when I want to use randomuser API).
"unexpected character at line 1 column 1 of the JSON data" always means the result isn't JSON, and almost always means (in the web context) that you're getting an error page instead.
Two issues:
(The main issue.) You're trying to make a cross-origin request (to http://localhost:777, but from some other origin, I'm guessing http://localhost:80 or similar), but not issuing the necessary CORS headers to enable the call from the origin you're making the call from. In contrast, https://randomuser.me enables requests from all origins.
(Not the main issue.) You're not checking that the request succeeded. This is (in my view) a failure of the fetch API, it has a major footgun in this regard I see fired here on SO almost every day. (Details in my blog post on it.). Add:
.then(resp => {
if (!resp.ok) {
throw new Error(resp.status);
}
})
...before your .then(resp => resp.json()).
Related
I am trying to fetch JSON data from the WordPress Developer Reference site. I need to search a keyword without knowing if it's a function, class, hook, or method, which is part of the url I need to fetch. So I'm using Promise.all to cycle through all possible urls. It works if the response.status <= 299, throwing the error immediately, and if the response is ok, then it continues to .then. Fine, but occasionally it will return an ok status if the JSON exists and only returns an empty array. So I need to check if the JSON data is an empty array, which I can't seem to do in the first part. I can only check in the second part as far as I know. And if it throws the error it doesn't continue trying the other urls. Any suggestions?
var keyword = 'AtomParser';
const refs = ['function', 'hook', 'class', 'method'];
// Store the promises
let promises = [];
// Cycle through each type until we find one we're looking for
for (let t = 0; t < refs.length; t++) {
const url =
'https://developer.wordpress.org/wp-json/wp/v2/wp-parser-' +
refs[t] +
'?search=' +
keyword;
// console.log(url);
promises.push(fetch(url));
}
Promise.all(promises)
.then(function(response) {
console.log(response[0]);
// Get the status
console.log('Status code: ' + response[0].status);
if (response[0].status <= 299) {
// The API call was successful!
return response[0].json();
} else {
throw new Error('Broken link status code: ' + response[0].status);
}
})
.then(function(data) {
// This is the HTML from our response as a text string
console.log(data);
// Make sure we have data
if (data.length == 0) {
throw new Error('Empty Array');
}
// ref
const reference = data[0];
// Only continue if not null or empty
if (reference !== null && reference !== undefined && data.length > 0) {
// Success
// Return what I want from the reference
}
})
.catch(function handleError(error) {
console.log('Error' + error);
});
Is there some way to get the JSON data in the first part so I can check if it's in an array while I'm checking the response status?
I would recommend encapsulating the success / failure logic for individual requests, then you can determine all the resolved and rejected responses based on the result of that encapsulation.
For example
const checkKeyword = async (ref, keyword) => {
const params = new URLSearchParams({ search: keyword });
const res = await fetch(
`https://developer.wordpress.org/wp-json/wp/v2/wp-parser-${encodeURIComponent(
ref
)}?${params}`
);
if (!res.ok) {
throw new Error(`${res.status}: ${await res.text()}`);
}
const data = await res.json();
if (data.length === 0) {
throw new Error(`Empty results for '${ref}'`);
}
return { ref, data };
};
Now you can use something like Promise.any() or Promise.allSettled() to find the first successful request or all successful requests, respectively
const keyword = "AtomParser";
const refs = ["function", "hook", "class", "method"];
const promises = refs.map((ref) => checkKeyword(ref, keyword));
// First success
Promise.any(promises)
.then(({ ref, data }) => {
console.log(ref, data);
})
.catch(console.error);
// All successes
Promise.allSettled(promises)
.then((responses) =>
responses.reduce(
(arr, { status, value }) =>
status === "fulfilled" ? [...arr, value] : arr,
[]
)
)
.then((results) => {
// results has all the successful responses
});
For whatever reason I couldn't get Phil's answer to work, so I ended up doing the following which works fine for me. (This is for a discord bot in case you're wondering what the other stuff is all about).
var keyword = 'AtomParser';
const refs = ['function', 'hook', 'class', 'method'];
// Store the successful result or error
let final: any[] = [];
let finalError = '';
// Cycle through each type until we find one we're looking for
for (let t = 0; t < refs.length; t++) {
const url =
'https://developer.wordpress.org/wp-json/wp/v2/wp-parser-' +
refs[t] +
'?search=' +
keyword;
console.log(url);
// Try to fetch it
await fetch(url)
.then(function (response) {
console.log(response);
// Get the status
console.log('Status code: ' + response.status);
if (response.status > 299) {
finalError = '`' + refs[t] + '` does not exist.';
throw new Error(finalError);
} else {
// The API call was successful!
return response.json();
}
})
.then(function (data) {
// This is the HTML from our response as a text string
console.log(data);
// Make sure we have data
if (data.length == 0) {
finalError = "Sorry, I couldn't find `" + keyword + '`';
throw new Error(finalError);
}
// Only continue if not null or empty
if (data[0] !== null && data[0] !== undefined && data.length > 0) {
for (let d = 0; d < data.length; d++) {
// Add it to the final array
final.push(data[d]);
}
}
})
.catch(function handleError(error) {
console.log(error);
});
}
if (final.length > 0) {
for (let f = 0; f < final.length; f++) {
// ref
const reference = final[f];
// Get the link
const link = reference.link;
// Get the title
var title = reference.title.rendered;
title = excerpt.replace('>', '>');
// Get the excerpt
var excerpt = reference.excerpt.rendered;
excerpt = excerpt.replace('<p>', '');
excerpt = excerpt.replace('</p>', '');
excerpt = excerpt.replace('<b>', '**');
excerpt = excerpt.replace('</b>', '**');
console.log(excerpt);
message.reply(
new discord.Embed({
title: `${title}`,
url: link,
description: `${excerpt}\n\n`,
footer: {
text: `WordPress Developer Code Reference\nhttps://developer.wordpress.org/`,
},
})
);
}
} else if (finalError != '') {
message.reply(finalError);
} else {
message.reply('Something went wrong...');
}
wp module
#Phil's answer puts you on the right track but I want to expand on some of his ideas. Use of URLSearchParamas is great but you can improve by using the high-level URL API and forego encodeURIComponent and constructing search params manually. Notice I'm putting this code in its own wp module so I can separate concerns more easily. We don't want all of this code leaking into your main program.
// wp.js
import { fetch } from "whatwg-fetch" // or your chosen implementation
const baseURL = "https://developer.wordpress.org"
async function search1(path, query) {
const u = new URL(path, baseURL)
u.searchParams.set("search", query)
const result = await fetch(u)
if (!result.ok) throw Error(`Search failed (${result.status}): ${u}`)
return result.json()
}
search1 searches one path, but we can write search to search all the necessary paths. I don't think there's any reason to get fancy with each path here, so just write them out -
// wp.js (continued)
function search(query) {
const endpoints = [
"/wp-json/wp/v2/wp-parser-function",
"/wp-json/wp/v2/wp-parser-hook",
"/wp-json/wp/v2/wp-parser-class",
"/wp-json/wp/v2/wp-parser-method"
]
return Promise
.all(endpoints.map(e => search1(e, query)))
.then(results => results.flat())
}
export { search }
main module
Notice we only exported search as search1 is internal to the wp module. Let's see how we can use it in our main module now -
// main.js
import { search } from "./wp.js"
for (const result of await search("database"))
if(result.guid.rendered)
console.log(`${result.title.rendered}\n${result.guid.rendered}\n`)
In this example, we first search for "database" -
wp_should_replace_insecure_home_url()
https://developer.wordpress.org/reference/functions/wp_should_replace_insecure_home_url/
wp_delete_signup_on_user_delete()
https://developer.wordpress.org/reference/functions/wp_delete_signup_on_user_delete/
get_post_datetime()
https://developer.wordpress.org/reference/functions/get_post_datetime/
wp_ajax_health_check_get_sizes()
https://developer.wordpress.org/reference/functions/wp_ajax_health_check_get_sizes/
wp_should_replace_insecure_home_url
https://developer.wordpress.org/reference/hooks/wp_should_replace_insecure_home_url/
comments_pre_query
https://developer.wordpress.org/reference/hooks/comments_pre_query/
users_pre_query
https://developer.wordpress.org/reference/hooks/users_pre_query/
WP_Object_Cache
http://developer.wordpress.org/reference/classes/wp_object_cache/
wpdb
http://developer.wordpress.org/reference/classes/wpdb/
WP_REST_Menu_Items_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_menu_items_controller/prepare_item_for_database/
WP_REST_Global_Styles_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_global_styles_controller/prepare_item_for_database/
WP_REST_Menus_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_menus_controller/prepare_item_for_database/
WP_REST_Templates_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_templates_controller/prepare_item_for_database/
WP_REST_Application_Passwords_Controller::prepare_item_for_database()
https://developer.wordpress.org/reference/classes/wp_rest_application_passwords_controller/prepare_item_for_database/
wpdb::db_server_info()
https://developer.wordpress.org/reference/classes/wpdb/db_server_info/
WP_REST_Attachments_Controller::insert_attachment()
https://developer.wordpress.org/reference/classes/wp_rest_attachments_controller/insert_attachment/
WP_Debug_Data::get_database_size()
https://developer.wordpress.org/reference/classes/wp_debug_data/get_database_size/
WP_REST_Meta_Fields::update_multi_meta_value()
https://developer.wordpress.org/method/wp_rest_meta_fields/update_multi_meta_value/
another search example
Now let's search for "image" -
for (const result of await search("image"))
if(result.guid.rendered)
console.log(`${result.title.rendered}\n${result.guid.rendered}\n`)
get_adjacent_image_link()
https://developer.wordpress.org/reference/functions/get_adjacent_image_link/
get_next_image_link()
https://developer.wordpress.org/reference/functions/get_next_image_link/
get_previous_image_link()
https://developer.wordpress.org/reference/functions/get_previous_image_link/
wp_robots_max_image_preview_large()
https://developer.wordpress.org/reference/functions/wp_robots_max_image_preview_large/
wp_getimagesize()
https://developer.wordpress.org/reference/functions/wp_getimagesize/
is_gd_image()
https://developer.wordpress.org/reference/functions/is_gd_image/
wp_show_heic_upload_error()
https://developer.wordpress.org/reference/functions/wp_show_heic_upload_error/
wp_image_src_get_dimensions()
https://developer.wordpress.org/reference/functions/wp_image_src_get_dimensions/
wp_image_file_matches_image_meta()
https://developer.wordpress.org/reference/functions/wp_image_file_matches_image_meta/
_wp_check_existing_file_names()
https://developer.wordpress.org/reference/functions/_wp_check_existing_file_names/
edit_custom_thumbnail_sizes
https://developer.wordpress.org/reference/hooks/edit_custom_thumbnail_sizes/
get_header_image_tag_attributes
https://developer.wordpress.org/reference/hooks/get_header_image_tag_attributes/
image_editor_output_format
https://developer.wordpress.org/reference/hooks/image_editor_output_format/
wp_image_src_get_dimensions
https://developer.wordpress.org/reference/hooks/wp_image_src_get_dimensions/
wp_get_attachment_image
https://developer.wordpress.org/reference/hooks/wp_get_attachment_image/
image_sideload_extensions
https://developer.wordpress.org/reference/hooks/image_sideload_extensions/
wp_edited_image_metadata
https://developer.wordpress.org/reference/hooks/wp_edited_image_metadata/
wp_img_tag_add_loading_attr
https://developer.wordpress.org/reference/hooks/wp_img_tag_add_loading_attr/
wp_image_file_matches_image_meta
https://developer.wordpress.org/reference/hooks/wp_image_file_matches_image_meta/
get_custom_logo_image_attributes
https://developer.wordpress.org/reference/hooks/get_custom_logo_image_attributes/
Custom_Image_Header
http://developer.wordpress.org/reference/classes/custom_image_header/
WP_Image_Editor_Imagick
http://developer.wordpress.org/reference/classes/wp_image_editor_imagick/
WP_Embed
http://developer.wordpress.org/reference/classes/wp_embed/
WP_Image_Editor
http://developer.wordpress.org/reference/classes/wp_image_editor/
WP_Customize_Background_Image_Setting
http://developer.wordpress.org/reference/classes/wp_customize_background_image_setting/
WP_Customize_Header_Image_Setting
http://developer.wordpress.org/reference/classes/wp_customize_header_image_setting/
WP_Image_Editor_GD
http://developer.wordpress.org/reference/classes/wp_image_editor_gd/
WP_Customize_Header_Image_Control
http://developer.wordpress.org/reference/classes/wp_customize_header_image_control/
WP_REST_Server::add_image_to_index()
https://developer.wordpress.org/reference/classes/wp_rest_server/add_image_to_index/
WP_REST_URL_Details_Controller::get_image()
https://developer.wordpress.org/reference/classes/wp_rest_url_details_controller/get_image/
WP_Image_Editor::get_default_quality()
https://developer.wordpress.org/reference/classes/wp_image_editor/get_default_quality/
WP_Theme_JSON::get_blocks_metadata()
https://developer.wordpress.org/reference/classes/wp_theme_json/get_blocks_metadata/
WP_Image_Editor_Imagick::pdf_load_source()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/pdf_load_source/
WP_Image_Editor_Imagick::write_image()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/write_image/
WP_Image_Editor_Imagick::maybe_exif_rotate()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/maybe_exif_rotate/
WP_Image_Editor_Imagick::make_subsize()
https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/make_subsize/
WP_Image_Editor_GD::make_subsize()
https://developer.wordpress.org/reference/classes/wp_image_editor_gd/make_subsize/
empty search result
Searching for "zzz" will yield no results -
for (const result of await search("zzz"))
if(result.guid.rendered)
console.log(`${result.title.rendered}\n${result.guid.rendered}\n`)
<empty result>
I am using request NPM package and request take two parameters
request (URL, callback);
Here I somehow want to pass extra argument to my callback function how do I do it.
This is the code I am trying to write
function extractIssues(url,filepath){
request(url,issueCb);
}
function issueCb(err,response,html)
{
if(err){
console.log(err+"at line 61");
}
else{
extractIssueData(html);
}
}
function extractIssueData(html){
let selTool = cheerio.load(html);
let arr = [];
let issueLinksArr = selTool(".flex-auto.min-width-0.p-2.pr-3.pr-md-2 > a");
let result="";
for(let i = 0;i<issueLinksArr.length;i++){
let issueLink = selTool(issueLinksArr[i]).attr("href");
let content = selTool(issueLinksArr[i]).text().trim().split("/n")[0];
let obj = {
link :issueLink,
content:content
}
let str = JSON.stringify(obj);
result = result + str + " ,"+ "\n" ;
}
console.log(result);
}
I want to use filepath in extractIssueData so I need to first catch it in issueCb how do I do it
I can't find proper answer.
This issue disappears entirely if you simplify to use a single function! The following should be equivalent to, if not an improvement on, your code:
let extractIssues = async (url, filepath) => {
// Wait for the html content of a `request` call
let html = await new Promise((resolve, reject) => {
// If an Error occurs reject with the error, otherwise resolve with
// html data
request(url, (err, res, html) => err ? reject(err) : resolve(html));
});
let selTool = cheerio.load(html);
// Collect href and text content values from <a> elements
let resultsArr = selTool(".flex-auto.min-width-0.p-2.pr-3.pr-md-2 > a")
.map(issueLink => ({
link: selTool(issueLink).attr("href"),
content: selTool(issueLink).text().trim().split("/n")[0]
}));
// Print the array of link+content data
console.log(resultsArr);
};
Note that within this function you have access to filepath, so you can use it as is necessary.
A solution without async looks like:
let extractIssues = (url, filepath) => {
request(url, (err, res, html) => {
if (err) throw err;
let selTool = cheerio.load(html);
// Collect href and text content values from <a> elements
let resultsArr = selTool(".flex-auto.min-width-0.p-2.pr-3.pr-md-2 > a")
.map(issueLink => ({
link: selTool(issueLink).attr("href"),
content: selTool(issueLink).text().trim().split("/n")[0]
}));
// Print the array of link+content data
console.log(resultsArr);
});
};
Once again this creates a scenario where filepath is available to be used as necessary within the function.
Note: If you are being "given instruction" not to use async you are being done a disservice; async is a core feature and major selling point of javascript. Once you become comfortable with async you will quickly regret ever having worked without it. I recommend you take the time to understand it! :)
I can create you an easy sample to use callback functions.
It's a stupid example I know but it helps you to understand how callbacks are working.
function myFunc(callback) {
let errMessage = "This is error callback";
let message = "This is normal message";
callback(errMessage, message);
}
function myCallbackFunc(err, result) {
if(!err) {
console.log(result);
return;
}
console.log(err);
}
myFunc(myCallbackFunc);
You won't use it like this but If you want to send a error callback, you should null to response param. Like this:
function myFunc(callback) {
let errMessage = "This is error callback";
let message = "This is normal message";
let somethingBadHappened = true;
if(somethingBadHappened) {
return callback(errMessage, null);
}
callback(null, message)
}
function myCallbackFunc(err, result) {
if(!err) {
console.log(result);
return;
}
console.log(err);
}
myFunc(myCallbackFunc);
I'm working on my front-end, and I've arrived at a roadblock. I'm trying to fetch data from my back-end, and it is actually fetching the data. But only after everything else? I'll show you.
$(function(){
function GetURLId() {
var url = window.location.href;
var path = url.substring(url.lastIndexOf('/') + 1);
var id = path.substring(path.lastIndexOf('?id=') + 4, path.lastIndexOf("?id") + 5)
return id;
}
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
})
});
});
So first I get which id I'm working with out of the URL. Then where the problem lays is the code under it. I'm able to fetch my data as it console.logs this:
id: 2
status: "Open"
damage: true
So the data does actually fetch from my back-end. But now, everytime I try to save the data it goes undefined. I've tried:
$(function(){
var rental = []; // Added an array
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
rental.push(rental[key] = data[key]);
})
});
console.log(rental['id']); // Returns undefined
});
And:
var rental = []; // Added an array outside of the function
$(function(){
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
rental.push(rental[key] = data[key]);
})
});
console.log(rental['id']); // Returns undefined
});
But! With the last one where the rental is outside of the function, I can actually call it in the console. And in the console it actually does return the value.
Inside Console:
> rental["id"]
< 2
Lastly I've tried to check the value of the key and value inside of the fetch, like this:
$(function(){
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
if(key == "status" && data[key] != "Reserved") {
console.log(`${key}: ${data[key]}`); // Returns damage: undefined 3 times
}
})
});
});
But this as well doesn't work. It returns damage: undefined 3 times in console.
So if anyone knows what is going on here it would be awesome!
Thanks alot in advance.
Fetch requests are asynchronous. This means that when you call fetch it might take a while to complete it, so JavaScript allows the rest of the code to continue without blocking. So logging anything to the console before your request has finished will obviously result in an empty array.
Also, Arrays are index-, not name based in JavaScript. However, because arrays are essentially objects it still works, but you should never do the following below.
var rental = [];
rental['id'] = 'foo';
console.log(rental['id']);
Instead use a plain object which is meant to be used that way.
var rental = {};
rental['id'] = 'foo';
console.log(rental['id']);
In your last example you seem to do everything just fine. Are you sure your fetched data does not have a value of undefined in its structure? It would help to see what the data looks like.
The answer: 2 errors in my code.
- First I didn't properly account for the asynchronous nature of the code.
- Second, when trying to fix it with another then block and executing my code in there. I didn't return a value in the proceeding then block, but the forEach instead.
fetch(url)
.then(resp => resp.json())
.then(data => {
var rentalStatus;
Object.keys(data).forEach(key => {
rental[key] = data[key];
if(key == "status") {
rentalStatus = data[key];
}
})
return rentalStatus;
})
.then(rentalStatus => {
console.log(rental["id"]); // This does return the id now!
if(rentalStatus == "Reserved") {
$("#assign-items").removeClass("d-none");
}
}).catch(error => {
console.log("Error:" + error);
});
I'm new to learning Node.js, so I'm still getting used to asynchronous programming and callbacks. I'm trying to insert a record into a MS SQL Server database and return the new row's ID to my view.
The mssql query is working correctly when printed to console.log. My problem is not knowing how to properly return the data.
Here is my mssql query - in addJob.js:
var config = require('../../db/config');
async function addJob(title) {
var sql = require('mssql');
const pool = new sql.ConnectionPool(config);
var conn = pool;
let sqlResult = '';
let jobID = '';
conn.connect().then(function () {
var req = new sql.Request(conn);
req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
jobID = result['recordset'][0]['JobID'];
conn.close();
//This prints the correct value
console.log('jobID: ' + jobID);
}).catch(function (err) {
console.log('Unable to add job: ' + err);
conn.close();
});
}).catch(function (err) {
console.log('Unable to connect to SQL: ' + err);
});
// This prints a blank
console.log('jobID second test: ' + jobID)
return jobID;
}
module.exports = addJob;
This is my front end where a modal box is taking in a string and passing it to the above query. I want it to then receive the query's returned value and redirect to another page.
// ADD NEW JOB
$("#navButton_new").on(ace.click_event, function() {
bootbox.prompt("New Job Title", function(result) {
if (result != null) {
var job = {};
job.title = result;
$.ajax({
type: 'POST',
data: JSON.stringify(job),
contentType: 'application/json',
url: 'jds/addJob',
success: function(data) {
// this just prints that data is an object. Is that because I'm returning a promise? How would I unpack that here?
console.log('in success:' + data);
// I want to use the returned value here for a page redirect
//window.location.href = "jds/edit/?jobID=" + data;
return false;
},
error: function(err){
console.log('Unable to add job: ' + err);
}
});
} else {
}
});
});
And finally here is the express router code calling the function:
const express = require('express');
//....
const app = express();
//....
app.post('/jds/addJob', function(req, res){
let dataJSON = JSON.stringify(req.body)
let parsedData = JSON.parse(dataJSON);
const addJob = require("../models/jds/addJob");
let statusResult = addJob(parsedData.title);
statusResult.then(result => {
res.send(req.body);
});
});
I've been reading up on promises and trying to figure out what needs to change here, but I'm having no luck. Can anyone provide any tips?
You need to actually return a value from your function for things to work. Due to having nested Promises you need a couple returns here. One of the core features of promises is if you return a Promise it participates in the calling Promise chain.
So change the following lines
jobID = result['recordset'][0]['JobID'];
to
return result['recordset'][0]['JobID']
and
req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
to
return req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
and
conn.connect().then(function () {
to
return conn.connect().then(function () {
You may need to move code around that is now after the return. You would also be well served moving conn.close() into a single .finally on the end of the connect chain.
I recommend writing a test that you can use to play around with things until you get it right.
const jobId = await addJob(...)
console.log(jobId)
Alternatively rewrite the code to use await instead of .then() calls.
I am trying to make a google image search, using google custom search engine, and a Google API key, to return a response, then from the response body, extract the URL, title and text snippets that describe the result. I get a result, but the result doesn't contain the items array, and the result's searchInformation's totalResults = 0: there has to be an image of cats on the internet. What it returns, I commented out, just before the ending curly braces and bracket of the app.route method's HTTP verb.
Please this question has been researched, and there are similar questions, here at StackOverflow, but they have not been answered. I don't know if maybe because the questions didn't have 'google-apis-explorer' tag
app.route('/')
.get(function(req, res) {
var endPoint = 'https://www.googleapis.com/customsearch/v1?key=' + API_KEY + '&cx=' +
CSE_ID + '&q=cats&num=10&searchType=image&start=1'
https.get(endPoint, (response) => {
const statusCode = response.statusCode;
const contentType = response.headers['content-type'];
var error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
// consume responseponse data to free up memory
response.resume();
return;
}
response.setEncoding('utf8');
var rawData = '';
response.on('data', (chunk) => { rawData += chunk;
});
response.on('end', () => {
try {
res.send(JSON.parse(rawData));
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
//res.sendFile(process.cwd() + '/views/index.html');
})
// what it returns.
{
"kind":"customsearch#search",
"url":{
"type":"application/json",
"template":"https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json"
},
"queries":{
"request":[
{
"title":"Google Custom Search - lectures",
"totalResults":"0",
"searchTerms":"cats",
"count":10,
"startIndex":1,
"inputEncoding":"utf8",
"outputEncoding":"utf8",
"safe":"off",
"cx":"013162268872379598895:76khcwygut4",
"searchType":"image"
}
]
},
"searchInformation":{
"searchTime":0.340305,
"formattedSearchTime":"0.34",
"totalResults":"0",
"formattedTotalResults":"0"
}
}
I was facing the same issue but my image search option was not enabled. So, check whether image search is enable on created search engine.
The answer to my question. You should make sure of the following in the custom search engine; image search is enabled. You will have to extract the image from the items array.