javascript es6 callback running first - callback

I've built the following event listener which will run the function isValidEmail, passing in a callback function NotInDatabase() which is scheduled to only run after an ajax call is complete. It appears though that NotInDatabase() runs immediately. Any idea why this would be happening?
Event listener:
const bindEvents = (form, inputSelector, errorSelector) => {
const emailInput = document.getElementById('email');
emailInput.addEventListener('blur', function(){
const emailValue = emailInput.value
isValidEmail('http://localhost:3001/user/email/'+emailValue,'data_placeholder', NotInDatabase())
});
}
isValidEmail with callback:
const isValidEmail = (url, data, success) => {
const xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
xhr.open('POST', url);
xhr.onreadystatechange = function() {
if (xhr.readyState>3 && xhr.status==200) {
success(xhr.responseText);
}
};
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded', 'Access-Control-Allow-Origin');
xhr.send(data);
return xhr;
}

Here
isValidEmail('http://localhost:3001/user/email/'+emailValue,'data_placeholder', NotInDatabase())
you do not pass NotInDatabase function as a callback into isValidEmail, but pass what it returns because NotInDatabase() is a function call.
Remove () to solve your problem

Related

How do I make 2 (or more) calls with Adobe PDF Services and skip using the file system (in between?)

It's fairly simple to make one call to Adobe PDF Services, get the result, and save it, for example:
// more stuff above
exportPdfOperation.execute(executionContext)
.then(result => result.saveAsFile(output))
But if I want to do two, or more, operations, do I need to keep saving the result to the file system and re-providing it (is that even a word ;) to the API?
So this tripped me up as well. In most demos, you'll see:
result => result.saveAsFile()
towards the end. However, the object passes to the completed promise, result, is a FileRef object that can then be used as the input to another call.
Here's a sample that takes an input Word doc and calls the API method to create a PDF. It then takes that and runs OCR on it. Both methods that wrap the API calls return FileRefs, so at the end I saveAsFile on it. (Note, this demo is using v1 of the SDK, it would work the same w/ v2.)
const PDFToolsSdk = require('#adobe/documentservices-pdftools-node-sdk');
const fs = require('fs');
//clean up previous
(async ()=> {
// hamlet.docx was too big for conversion
const input = './hamlet2.docx';
const output = './multi.pdf';
const creds = './pdftools-api-credentials.json';
if(fs.existsSync(output)) fs.unlinkSync(output);
let result = await createPDF(input, creds);
console.log('got a result');
result = await ocrPDF(result, creds);
console.log('got second result');
await result.saveAsFile(output);
})();
async function createPDF(source, creds) {
return new Promise((resolve, reject) => {
const credentials = PDFToolsSdk.Credentials
.serviceAccountCredentialsBuilder()
.fromFile(creds)
.build();
const executionContext = PDFToolsSdk.ExecutionContext.create(credentials),
createPdfOperation = PDFToolsSdk.CreatePDF.Operation.createNew();
// Set operation input from a source file
const input = PDFToolsSdk.FileRef.createFromLocalFile(source);
createPdfOperation.setInput(input);
let stream = new Stream.Writable();
stream.write = function() {
}
stream.end = function() {
console.log('end called');
resolve(stream);
}
// Execute the operation and Save the result to the specified location.
createPdfOperation.execute(executionContext)
.then(result => resolve(result))
.catch(err => {
if(err instanceof PDFToolsSdk.Error.ServiceApiError
|| err instanceof PDFToolsSdk.Error.ServiceUsageError) {
reject(err);
} else {
reject(err);
}
});
});
}
async function ocrPDF(source, creds) {
return new Promise((resolve, reject) => {
const credentials = PDFToolsSdk.Credentials
.serviceAccountCredentialsBuilder()
.fromFile(creds)
.build();
const executionContext = PDFToolsSdk.ExecutionContext.create(credentials),
ocrOperation = PDFToolsSdk.OCR.Operation.createNew();
// Set operation input from a source file.
//const input = PDFToolsSdk.FileRef.createFromStream(source);
ocrOperation.setInput(source);
let stream = new Stream.Writable();
stream.end = function() {
console.log('end called');
resolve(stream);
}
// Execute the operation and Save the result to the specified location.
ocrOperation.execute(executionContext)
.then(result => resolve(result))
.catch(err => reject(err));
});
}

Puppeteer and express can not load new data using REST API

I'm using puppeteer to scrape page that has contents that change periodically and use express to present data in rest api.
If I turn on headless chrome to see what is being shown in the browser, the new data is there, but the data is not showing up in get() and http://localhost:3005/api-weather. The normal browser only shows the original data.
const express = require('express');
const server = new express();
const cors = require('cors');
const morgan = require('morgan');
const puppeteer = require('puppeteer');
server.use(morgan('combined'));
server.use(
cors({
allowHeaders: ['sessionId', 'Content-Type'],
exposedHeaders: ['sessionId'],
origin: '*',
methods: 'GET, HEAD, PUT, PATCH, POST, DELETE',
preflightContinue: false
})
);
const WEATHER_URL = 'https://forecast.weather.gov/MapClick.php?lat=40.793588904953985&lon=-73.95738513173298';
const hazard_url2 = `file://C:/Users/xdevtran/Documents/vshome/wc_api/weather-forecast-nohazard.html`;
(async () => {
try {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on("request", request => {
console.log(request.url());
request.continue();
});
await page.goto(hazard_url2, { timeout: 0, waitUntil: 'networkidle0' });
hazard = {
"HazardTitle": "stub",
"Hazardhref": "stub"
}
let forecast = await page.evaluate(() => {
try {
let forecasts = document.querySelectorAll("#detailed-forecast-body.panel-body")[0].children;
let weather = [];
for (var i = 0, element; element = forecasts[i]; i++) {
period = element.querySelector("div.forecast-label").textContent;
forecast = element.querySelector("div.forecast-text").textContent;
weather.push(
{
period,
forecast
}
)
}
return weather;
} catch (err) {
console.log('error in evaluate: ', err);
res.end();
}
}).catch(err => {
console.log('err.message :', err.message);
});
weather = forecast;
server.get('/api-weather', (req, res) => {
try {
res.end(JSON.stringify(weather, null, ' '));
console.log(weather);
} catch (err) {
console.log('failure: ', err);
res.sendStatus(500);
res.end();
return;
}
});
} catch (err) {
console.log('caught error :', err);
}
browser.close();
})();
server.listen(3005, () => {
console.log('http://localhost:3005/api-weather');
});
I've tried several solutions WaitUntil, WaitFor, .then and sleep but nothing seems to work.
I wonder if it has something to do with express get()? I'm using res.end() instead of res.send() is because the json looks better when I use res.end(). I don't really know the distinction.
I'm also open to using this reload solution. But I received errors and didn't use it.
I also tried waitForNavigation(), but I don't know how it works, either.
Maybe I'm using the wrong search term to find the solution. Could anyone point me in the right direction? Thank you.

Port botbuilder restify listener to sailsjs route

I'm following the botbuilder demos here - https://github.com/Microsoft/BotBuilder/blob/master/Node/examples/demo-skype/app.js
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});
// Create chat bot
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
var bot = new builder.UniversalBot(connector);
server.post('/api/messages', connector.listen());
I want to host this bot inside SailsJS.
I've routed the call as follows:
// config/routes.js
'POST /api/messages': {
controller: 'BotframeworkController',
action: 'listen',
},
And the controller:
var builder = require('botbuilder');
var botconfig = sails.config.botframework;
var connector = new builder.ChatConnector({
appId: botconfig.MICROSOFT_APP_ID,
appPassword: botconfig.MICROSOFT_APP_PASSWORD
});
var bot = new builder.UniversalBot( connector, function( session ) {
session.send("%s, I heard: %s", session.userData.name, session.message.text);
});
// Add help dialog
bot.dialog('help', function (session) {
session.send("I'm a simple echo bot.");
}).triggerAction({ matches: /^help/i });
module.exports = {
listen: function( req, res, next ){
sails.log.debug('BotframeworkController.listen... started');
sails.log.debug(req.body);
return connector.listen( req, res );
// var test = connector.listen( req, res );
// sails.log.debug(test );
},
}
I don't get any errors - that I can see - but there is no response returned to the client.
Any ideas/suggestions would be appreciated?
I haven't worked with SailsJS but it looks like it would call the listen method of BotframeworkController upon receiving a POST to /api/messages. Am I reading it right?
The connector.listen() itself is not the handler, it's the path to the handler. It returns a function that will handle the incoming request and response. Try it like this instead:
module.exports = {
listen: connector.listen()
}

Protractor: Getting undefined while trying to return a value

I have written a function which sends a GET request and returns the response.
this.generateToken = function() {
var options = {
uri: 'http://localhost:10000/token',
method: 'GET',
headers: {
'Authorization': "YWRtaW46YWRtaW4="
},
};
request(options, function (error, response, body) {
var messageresponse = response.body.toString();
console.log(messageresponse); //I am able to print the response
return messageresponse;
});
};
I am able to print the value of 'messageresponse' variable inside request().
This function is being called from one of my test:
it('Post a GET request and generate a response', function () {
var response = commonFunctionObj.generateToken();
response.then(function(value){ //Getting below mentioned error on this line
console.log(value);
});
});
Getting error: TypeError: Cannot read property 'then' of undefined in teh calling function.
Can someone please help?
You need to create a promise and resolve it once to receive the response.
Look at the below code.
this.generateToken = function() {
var deffered = protractor.promise.defer(); //create a promise
var options = {
uri: 'http://localhost:10000/token',
method: 'GET',
headers: {
'Authorization': "YWRtaW46YWRtaW4="
},
};
request(options, function (error, response, body) {
var messageresponse = response.body.toString();
console.log(messageresponse);
deffered.fulfill(messageresponse); //Instead of returning the response message, fulfill the promise that we created early.
});
return deffered.promise; //return the created promise.
};
Now you can call the generateToken() method inside any of your test that will return a promise which is resolved only when the response is recieved from API call.
it('Post a GET request and generate a response', function () {
var response = commonFunctionObj.generateToken();
response.then(function(value){
console.log(value);
});
});
I think you can do it as follows;
this.generateToken = function() {
var deferred = protractor.promise.defer();
var options = {
uri: 'http://localhost:10000/token',
method: 'GET',
headers: {
'Authorization': "YWRtaW46YWRtaW4="
},
};
request(options, function (error, response, body) {
var messageresponse = response.body.toString();
deferred.fulfill(messageresponse);
});
return deferred.promise;
};
it('Post a GET request and generate a response', function () {
var response = commonFunctionObj.generateToken();
response.then(function(value){ //Getting below mentioned error on this line
console.log(value);
});
});
Explanation;
You can't use .then with generateToken's return. Because there is no return inside of that function. You need to make a promise (protractor.promise) for using then inside of that. Then, you can use .then with generateToken function.
You need to write print response logic in callback function, which is to resolve the promises or handling Asynchronous behavior
Code Snippet:
it('Post a GET request and generate a response', function () {
var response = commonFunctionObj.generateToken(function(err,res){
res.then(function(value){
console.log(value); //or return value
});
});
});

GoogleAuth library loading with promises

I am trying to load google authentication library using promises, but I fail when I try to call gapi.auth2.getAuthInstance() and return it in promise;
Here's how I am doing this:
var loadPlatform = function ($q) {
var deferred = $q.defer(),
platform = document.createElement('script');
platform.src ='https://apis.google.com/js/platform.js';
platform.type = 'text/javascript';
platform.async = true;
platform.defer = true;
platform.onload = deferred.resolve;
platform.onerror = deferred.reject;
document.body.appendChild(platform);
return deferred.promise;
};
//I return this from other function
return loadPlatform($q)
.then(function () {
var deferred = $q.defer();
gapi.load('auth2', function () {
deferred.resolve(gapi.auth2);
});
return deferred.promise;
})
.then(function (auth2) {
//This function retuns Promise
//https://developers.google.com/identity/sign-in/web/reference#gapiauth2initparams
return auth2.init(params);
})
.then(function (GoogleAuth) {
//Here I should have solved GoogleAuth object
});
Everything works until I return auth2.init(params) then browser freezes.
What's happening here?
I just experienced the same issue.
It seems like you can't chain the init() promise of the auth2 object.
I had to wrap around it to avoid the browser freeze.
return new Promise<void>(resolve => {
gapi.auth2.init({
client_id: this._clientId,
scope: 'profile'
}).then(() => resolve());
})
Also it was interesting that I could not apply the resolve function directly.
.then(resolve);
Update
As said above, the returned object of the init() call is not a promise, it is kind of a wrapper and only returns a real promise once you called the .then method
return gapi.auth2.init({
client_id: this._clientId,
scope: 'profile'
}).then();
// Auth2 only returns a promise, when we chained into the PromiseLike object once.