The docs on requestQueue.getInfo().
Code
function printRequestQueue(requestQueue){
let { totalRequestCount, handledRequestCount, pendingRequestCount } =
requestQueue.getInfo()
.then(()=> {
console.log('\nRequest Queue:\n total:', this);
console.log('\nRequest Queue:\n total:', totalRequestCount);
console.log(' handled:', handledRequestCount, '\n pending:', pendingRequestCount);
})
.catch( (error) => console.log(error));
}
When run in the runtime environment Apify.main(async () => { ... }, it returns undefined:
Request Queue:
total: undefined
handled: undefined
pending: undefined
You don't seem to be returning the contents of the response back from the operation promise and so the variables are indeed uninitialized at the time of logging them. Operation itself should be returning this result and you can confirm so by logging the result of the promise - e.g. .then(response) => {console.log(response)}:
https://sdk.apify.com/docs/typedefs/request-queue-info
Thanks to Vasek. I post below 2 solutions:
Solution 1
async function printRequestQueue (requestQueue){
var { totalRequestCount, handledRequestCount, pendingRequestCount } = await
requestQueue.getInfo();
console.log(`Request Queue info:` );
console.log(' - handled :', handledRequestCount);
console.log(' - pending :', pendingRequestCount);
console.log(' - total:' , totalRequestCount);
}
Solution 2
function printRequestQueue (requestQueue){
requestQueue.getInfo().then((response)=> {
console.log('total:', response.totalRequestCount);
console.log('handled:', response.handledRequestCount, '\n pending:',
response.pendingRequestCount);
console.log('\nFull response:\n', response); })
.catch( (error) => console.log(error));
}
One may read full explanation in here.
Related
I am following the guide at official Angular documentation at https://angular.io/guide/http.
The handleError function in the post request has 2 arguments and it's giving me an error of 'expected 1 argument but got 2'.
The code for error handling is:
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something bad happened; please try again later.');
};
The code for the post request is:
/** POST: add a new hero to the database */
addHero (hero: Hero): Observable<Hero> {
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions)
.pipe(
catchError(this.handleError('addHero', hero))
);
}
Does the function need no argument in any case?
I think it's trying to call the function again with the argument of hero in case of error. Is that so?
Thank you.
The angular guide is actually wrong/confusing on this, or at least, they did not show the right examples. When you do something like this:
catchError(this.handleError('addHero', hero))
The handleError should accept two parameters, and also return a function which accepts one parameter. So something like this:
handleError<T>(action: string, object: T): (e: HttpErrorResponse) => Observable<never> {
return (e: HttpErrorResponse) => {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError(
`Something bad happened while performing action: ${action}, on object ${object}`
);
};
}
If you want the handleError be like the one you have:
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
return throwError(
'Something bad happened; please try again later.'
);
};
You should change the way you pass this into the catchError:
catchError((error: HttpErrorResponse) => this.handleError(error));
If you are not accessing the this context from the handleError you can do the following:
catchError(this.handleError)
In this part of the guide, it's explained better. It's just that the examples in the POST and PUT sections are missing the correct implementation of the handleError method
I deployed my angular 6 app to Heroku ( https://angulardictionary.herokuapp.com/).
But I'm getting the error SyntaxError: Unexpected token < in JSON at position 0 at JSON.parse.
I understand what this error means: The response returns html instead of JSON.
My question is: how can I fix it?
I tried:
res.send(object)
res.json(object)
Here's my code:
server.js
app.get('*', function(req,res) {
res.sendFile(path.join(__dirname +'/dist/frontend/index.html'));
});
app.get('/api/words', function(req, res){
fs.readFile('newWords.xml', 'utf-8', function (err, data){
if(err){
console.log('error');
//res.send(err);
} else{
parser.parseString(data, function (err, result) {
let words = result['entry']['form'];
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(words));
web.service.ts:
getWords(name: string, option: any):Observable<Word[]>{
return this.http.get<Word[]>('/api/words',{
params: {
name:name,
option:option
}
}
);
}
and I call this function in: home.component.ts:
getWordList(){
this.webservice.getWords(this.spelling, this.selected)
.subscribe((res: Array<Word>)=> {
this.elements = res.filter(d=> d.orth == this.spelling || d.asuddimIsem
== this.spelling);
}
}
It seems as if all the http calls go directly to the default route (app.get('*', function(req,res)), skipping (app.get('/api/words')).
It seems as if all the http calls go directly to the default route (app.get('*', function(req,res)), skipping (app.get('/api/words')) this is correct. The order in which routes are defined matters. You have to put the wildcard * route at last. As for the other API, you may not need to stringify JSON.stringify() the response, you can simply do res.send(words).
As the title states, I have a variable which is a javascript object, i'm comparing it with another js object by stringifying them. The problem is that the variable is completely accessible without calling the keys, so these
if(JSON.stringify(response) == JSON.stringify(lastcmd))
if(JSON.stringify(response.id) == JSON.stringify(lastcmd))
work perfectly fine, but accessing lastcmd's id key will cause it to throw undefined.
if(JSON.stringify(response) == JSON.stringify(lastcmd.id))
full code link here
Edit: Here's the JSON
{ "id" : "001", "app": "msgbox", "contents": { "title": "Newpaste", "message": "I'm a edited paste!" } }
Edit2: Here's the code on the post
const { BrowserWindow, app, dialog, ClientRequest } = require("electron");
const axios = require("axios");
const url = require("url");
let win = null;
let lastcmd;
function grabCurrentInstructions(fetchurl) {
return axios
.get(fetchurl)
.then(response => {
// handle success
//console.log(response.data);
return response.data;
})
.catch(function(error) {
// handle error
console.log(error);
});
}
function boot() {
//console.log(process.type);
win = new BrowserWindow({
resizable: true,
show: false,
frame: false
});
win.loadURL(`file://${__dirname}/index.html`);
//Loop everything in here every 10 seconds
var requestLoop = setInterval(getLoop, 4000);
function getLoop() {
grabCurrentInstructions("https://pastebin.com/raw/i9cYsAt1").then(
response => {
//console.log(typeof lastcmd);
//console.log(typeof response);
if (JSON.stringify(response.app) == JSON.stringify(lastcmd.app)) {
console.log(lastcmd.app);
clearInterval(requestLoop);
requestLoop = setInterval(getLoop, 4000);
} else {
lastcmd = response;
switch (response.app) {
case "msgbox":
dialog.showMessageBox(response.contents);
//console.log(lastcmd);
clearInterval(requestLoop);
requestLoop = setInterval(getLoop, 1000);
}
}
}
);
}
}
app.on("ready", boot);
And here's the error:
(node:7036) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'id' of undefined
at grabCurrentInstructions.then.response (C:\Users\The Meme Machine\Desktop\nodejsprojects\electronrat\index.js:42:64)
at process._tickCallback (internal/process/next_tick.js:68:7)
Thanks to user str I saw that my lastcmd was undefined when I ran the comparison the first time, this would break it and thereby loop the same error over and over, by addding
grabCurrentInstructions("https://pastebin.com/raw/i9cYsAt1").then(
response => {
lastcmd = response;
}
);
below this line
win.loadURL(`file://${__dirname}/index.html`);
I made sure that the last command sent while the app was offline wouldn't be executed on launch and fixing my problem at the same time!
I would like to construct a Promise, but defer resolution until later. The code below creates a promise, but it is resolved immediately. How can I control when the promise gets evaluated?
var p = new Promise((resolve, reject) => {
resolve(1);
})
.then((p1) => {
console.log(p1 + 1);
});
UPDATE: To clarify, the reason for wanting to separate the declaration of the promise from its execution is to add then callbacks dynamically, based on some arguments.
You can pass resolve and reject to whatever asynchronous function you want to use. And such function can call it whenever it is done doing its work. Here is an example runnable in Node. If you run this, it will execute ls -l in your current directory. The execSomething function just takes callbacks and the promiseToExec function passed the resolve, reject callbacks to execSomething rather than call either of them immediately.
const childProcess = require("child_process");
function execSomething(command, options, onSuccess, onError) {
childProcess.exec(command, options, (err, stdout, stderr) => {
if (err) {
onError(err);
}
onSuccess(stdout, stderr);
});
}
function promiseToExec(command, options) {
return new Promise((resolve, reject) => {
execSomething(command, options, resolve, reject);
});
}
promiseToExec("ls -l").then(console.log.bind(console));
Kazlauskis suggested doing this:
var resolve;
var promise = new Promise(function(fulfill) {
resolve = fulfill;
});
Don't do this!.
When an exception happens in the callback you pass to new Promise, the specification for promises is such that the exception will automatically be converted into a promise rejection. So if anything does throw Error... inside the callback you get automatic conversion.
If you save the resolve callback and move your logic outside of the callback you pass to new Promise, then you do not get this automatic conversion. An exception thrown outside the callback will just be passed up the stack without being converted to a promise rejection. This is bad because it requires users of your function to use .catch to catch rejected promises and try...catch for thrown exceptions. This is a bad design practice.
Here's code illustrating the issue:
// This is how things should be done.
function makeGoodPromise(num) {
return new Promise((resolve) => {
if (num < 0) {
throw new Error("negative num");
}
resolve(num);
});
}
// This is a bad approach because it will sometimes result in synchronous
// exceptions.
function makeBadPromise(num) {
let resolve;
const p = new Promise((fullfil) => {
resolve = fullfil;
});
if (num < 0) {
throw new Error("negative num");
}
resolve(num);
return p;
}
// Shoring up the bad approach with a try... catch clause. This illustrates what
// you need to do convert the exception into a rejection. However, why deal with the
// additional scaffolding when you can just take the simpler approach of not
// leaking the callbacks??
function makeBadPromise2(num) {
let resolve, reject;
const p = new Promise((fullfil, deny) => {
resolve = fullfil;
reject = deny;
});
try {
if (num < 0) {
throw new Error("negative num");
}
resolve(num);
}
catch (e) {
reject(e);
}
return p;
}
makeGoodPromise(-1).catch(() => console.log("caught the good one!"));
try {
makeBadPromise(-1).catch(() => console.log("caught the bad one!"));
}
catch(e) {
console.log("Oops! Synchronous exception: ", e);
}
makeBadPromise2(-1).catch(() => console.log("caught the bad2 one!"));
When I execute it in Node, this is the output:
Oops! Synchronous exception: Error: negative num
at makeBadPromise (/tmp/t12/test2.js:17:11)
at Object.<anonymous> (/tmp/t12/test2.js:48:3)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:394:7)
at startup (bootstrap_node.js:149:9)
caught the good one!
caught the bad2 one!
Not entirely sure what you are asking- the code below demonstrates that construction of the promise and calling then happen in the same order, but may execute at different times. Change the values for wait1 and wait2 and see how the output is different, but the code works correctly regardless of the timing.
I think it will be up to you to implement the promise code so that it waits for whatever condition you want to wait for. In the example, it is a simple setTimeout, but you could conceivably do anything to defer execution.
You'll probably need to use Chrome to see these results in your browser:
var wait1 = 2000;
var wait2 = 1000;
function log(...str) {
var li = document.createElement('li');
str.forEach((s) => {
li.appendChild(document.createTextNode(s));
});
document.getElementById("log").appendChild(li);
}
var p = new Promise((resolve, reject) => {
setTimeout(() => {
log("Resolving promise!");
resolve(1);
}, wait1);
});
log("Promise created!");
setTimeout(() => {
log("Calling 'then'");
p.then((p1) => {
log("Value:", p1 + 1);
});
}, wait2);
<ol id="log" />
EDIT: as Luis points out in another answer, if an exception is thrown it will not be caught by the promise constructor but leaves this handling to the outer scope. This might be desirable in some situations, but I would also recommend using constructors and passing the resolver function as a callback. More on this here: Resolve Javascript Promise outside function scope
You can:
var resolve;
var promise = new Promise(function(fulfill) {
resolve = fulfill;
});
// now you can resolve the promise whenever you want
promise.then(function() {
console.log('done!');
});
resolve();
I parse an json object and for each element, i need to execute many queries.
In first, a "select" query and depending on the result, i execute an insert or an update.
I would like use async.js and knex.js
The issue it's the order of execution is not the searched order
async.each(newContent,function(e){
//var e=JSON.stringify(element),
var z=-1,
devicepresenceId = e.device_presence_id;
//console.log(e);
async.waterfall([
function(cb) {
knex('jos_joomrh_event_employee_hours_presence')
.whereRaw('device_presence_id=?', devicepresenceId)
.select('id', 'applied_at', 'applied_at_end')
.debug()
.then(function (rows) {
console.log(rows);
z = _.keys(rows).length;
console.log('rows0', z);
cb(null,z);
})
.catch(function (e) {
console.log(e)
reject(e)
})
cb(null,z);
},
function(z,cb){
console.log('z',z);
if (parseInt(z)==0)
{
console.log('insertHoursPresence');
//insertHoursPresence(e)
}
else{
console.log('updateHoursPresence');
//updateHoursPresence(e)
}
cb(null,'two')
}
],
function(err,z){
if(err)console.log(err);
console.log(z);
}
)}
)}
In fact; it executed the second function and and the cb function and after the first function with knex.:
Thanks for your help
Mdouke
In the knex part, you have a call to "cb(null,z)", you have to "move" that call inside catch function (but replacing reject(e) part). Your problem is that you're calling cb() function outside knex, of course it is called immediately independent of knex result)