Meteor synchronous function call on the client - javascript

I'm using Meteor and React, and I'm trying return data from a third party javascript function
The function takes a callback and returns a value. The function takes a few seconds to resolve
At the moment the callback returns an undefined value but after a few seconds a console log will display the correct data
My current code is as follows
// ON THE CLIENT
// callback function that returns a deviceId
const callback = function( data ) {
// this callback fires with the correct data after a couple of seconds
console.log("Callback ", data);
return data;
};
// async function that calls third party function with callback
async function getDeviceId() {
const res = await captureDeviceId(callback);
return await res;
}
let response = getDeviceId().then( function(value) {
return value;
});
console.log("res", response);
The response returns a promise but does not resolve
Return {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
How can I wait for the functions response before returning the value?
I've tried Meteor wrapAsync, async-await and Promises without success.
Any help would be appreciated
Cheers,

getDeviceId returns here a promise (even if you do a return inside the .then callback). If you want to ge the value, do it like below:
var response;
getDeviceId().then( function(value) {
response = value;
});

Related

Async Promise returns undefined or zone aware promise

When calling a function that returns a promise, comes back as undefined unless async operators are removed, then returns ZoneAwarePromise, but contains no data.
I know the query returns data when the function executes, it however does not seem to pass that data to the actual return part of the function call.
I have looked at several Stack questions that have not answered this question including this question:
Async/Await with Request-Promise returns Undefined
This is using a REST endpoint to pull data, the console.logs do show the data is correct, however return comes back as undefined
this.allPeople.forEach(async person => {
const dodString = await this.getRelatedRecords(person); //undefined
}
This is the main function that returns a promise / data
async getRelatedRecords(person) {
// function truncated for clarity
// ...
//
console.warn('This async should fire first');
selPeopleTable.relationships.forEach(relationship => {
allRelationshipQueries.push(
arcgisService.getRelatedTableData(
selPeopleTable.url, [person[oidField.name]], relationship.id, relationship.name),
);
});
await Promise.all(allRelationshipQueries).then(allResults => {
console.log('Inside the Promise');
// The Specific node I am looking for
const data = allResults[1].results.relatedRecordGroups[0].relatedRecords[0].attributes.dod;
console.log(data); // Shows correctly as the data I am looking for
return data;
}).catch(function(data){
console.log('there might be data missing', data);
});
}
Removing the ASYNC operators cause the getRelatedRecords() to fire after the containing function and / or return a 'ZoneAwarePromise' which contains no data. I need getRelatedRecords() to fire first, then to run the rest of the code.
I can provide more snippets if need be.
Zone Aware Promise
When the Async operators are (I think) setup correctly
You need to return this as well:
await Promise.all(allRelationshipQueries).then(allResults => {
console.log('Inside the Promise');
// The Specific node I am looking for
const data = allResults[1].results.relatedRecordGroups[0].relatedRecords[0].attributes.dod;
console.log(data); // Shows correctly as the data I am looking for
return data;
})
return in the above block is returning but all of this is in the scope of the arrow function which is then(allResults => { so you also need to return this function like this:
return await Promise.all(allRelationshipQueries).then(allResults => {
Approach #2:
Second way would be to store that into variable like this:
let dataToReturn = await Promise.all(allRelationshipQueries).then(allResults => {
console.log('Inside the Promise');
// The Specific node I am looking for
const data = allResults[1].results.relatedRecordGroups[0].relatedRecords[0].attributes.dod;
console.log(data); // Shows correctly as the data I am looking for
return data;
}).catch(function(data){
console.log('there might be data missing', data);
});
return dataToReturn;

How to get data from async functions and after getting data allow the next code to execute

I get some data from mongodb using mongoose find() and perform some validation on that data, but the problem is that this function is async and it does not wait for the data to be completed and execute the next code.
and when the next code is executed it enables to perform because it has null data. then i wrote my validation logic in the async function so that when data is available only then it move to next code but on every return it sends undefined data.
function isValidObject(obj) {
schemaData.find({}, (error, data) => { // calls data from db
var contactSchema = data; // this is data i need
if(//validation fails){
return "wrong data";// every time it returns undrfined on every
// condition
}
});
}
var validationResp = isValidObject(obj);
console.log(validationResp); // output is undefined
i also used "await" to wait for the data, but in that case it return [object promise] on every return statement
use async/await
In your case:
async function isValidObject(obj) {
let data = await schemaData.find({}); // wait until it resolve promise
//do your validaion
return data;
}
isValidObject(obj).then((validationResp)=>{console.log(validationResp)});
use the then() method it return a promise
var promise1 = new Promise(function(resolve, reject) {
resolve('Success!');
});
promise1.then(function(value) {
console.log(value);
// expected output: "Success!"
});
more details at MDN Using the then method
Are you familiar with "promises".You can use ".then(callback)". It will wait until async function is executed. And you can perform your validation in the callback function
User.findById(id)
.then(function(user) {
if (!user) {
return "here you return an error";
}
return "you return OK with payload from database";
})
.catch(next);
What is happening in your case is that when you assign var validationResp = isValidObject(obj); the function isValidObject(obj) has not returned anything and has only scheduled a callback(This is a very important concept when working with callbacks). As pointed out above you need to use Promises. The below is an example of your case as to how you can use Promises.
function isValidObject(obj){
return new Promise((resolve,reject) => {
schemaData.find({}, (error, data) => { // calls data from db
if(validation fails){
reject(error)// every time it returns undrfined on every
// condition
}else{
var contactSchema = data; // this is data i need
resolve(data)// You can resolve the promise with the data directly instead
// of assigning it to a variable or you can use (resolve(contactSchema))
}
})
})
}
After this when you want to use the data you can use do something like the below code snippet.
isValidObject(obj)
.then(result => {
// Use the result object here. This is the result from the Database
})
.catch(error => {
//Handle the Error
})

Call $http inside AngularJS function

I've been trying for a while to get the data from this call, but it always returns "undefined"
httpCall = function(sTformName) {
let sURL = "https://urlthisone/api/",
response;
$http.get(sURL)
.success(function(data) {
response = data;
});
}
Any ideas on what I'm doing wrong?
Thanks in advance.
You can return and resolve the promise...
httpCall = function(sTformName) {
let sURL = 'https://urlthisone/api/',
return $http.get(sURL);
}
httpCall('myForm').then(response => {
console.log(response.data);
});
$http.get is an asynchronous call and must be handled accordingly, in this case, by resolving the returned Promise
You're making an async call, and it will not return a value. It calls success and inside success you need to use a callback method in order to get the value you want, and work with it.
function doSomethingWithTheData(data) {
// process the data here.
}
httpCall = function(sTformName, callback) {
let sURL = "https://urlthisone/api/",
response;
$http.get(sURL)
.success(function(data) {
callback(data); // here's where we call the callback
});
}
// call it with the callback
httpCall(fornName, doSomethingWithTheData);
Please, see documentation - https://docs.angularjs.org/api/ng/service/$http#get
According to it, if you use angular.js 1.4.3+, $http.get(sURL) returns promise. So you need $http.get(sURL).then(...)
Also, see $http.get(...).success is not a function might will help

Return html response to calling function in nodejs

I've got this Node.js snippet.
var requestify = require('requestify');
// [...]
function remoterequest(url, data) {
requestify.post(url, data).then(function(response) {
var res = response.getBody();
// TODO use res to send back to the client the number of expected outputs
});
return true;
}
I need to return res content instead of true, back to the caller.
How can I do that?
In this case, the requestify's method is asyncronous, therefore, the returned value is not possible to be retrieved (since it's not generated yet).
How can I solve it? How can I send a synchronous HTTP POST request (even without requestify)?
you need to return a promise and use it in the then method of the promised returned by remoteRequest :
var requestify = require('requestify');
// [...]
function remoterequest(url, data) {
return requestify
.post(url, data)
.then((response) => response.getBody());
}
//....
remoteRequest('/foo', {bar: 'baz'}).then(res => {
//Do something with res...
});
Note that it still won't be a synchronous POST though, but you will be able to use response.getBody() when available, If this is what you wanted
You can refer to this discussion about how to use content returned from a promise How do I return the response from an asynchronous call?
As mentionned by #Logar, you can't use directly the content returned in your promise. You must call your method returning a promise first, and use .then to make the returned content available.
Example:
var requestify = require('requestify');
// [...]
// This function returns a promise, so you have to call it followed by `.then` to be able to use its returned content
function remoterequest(url, data) {
requestify
.post(url, data)
.then((response) => {
return response.getBody();
});
}
//....
//... Some other code here
//....
// Make a call to your function returning the promise
remoterequest('your-url-here', {data-to-pass-as-param})
.then((res) => { // Calling `.then` here to access the returned content from `remoterequest` function
// Now you can use `res` content here
});

Function doesn't return $http response

I have created a function expression and assigned it to scope, the idea being that the function will initiate an $http request, get a property and then return it.
$scope.getRequestDigest = function () {
var url = urlParams['SPAppWebUrl'] + '/_api/contextinfo';
$http.post(url)
.success(function (res) {
return res;
});
}
However when I call $scope.getRequestDigest() it simply returns undefined, presumably because the ajax call hasn't completed yet. Is there any way to delay the return until the $http request is complete? I've tried using the .success() promise but that doesn't seem to work.
$http.post returns a promise (see $q). In order to use the result, bind res to $scope.res:
controller:
$scope.getRequestDigest = function () {
var url = urlParams['SPAppWebUrl'] + '/_api/contextinfo';
$http.post(url)
.success(function (res) {
$scope.res = res;
});
}
Then, you can use $scope.res (or res in the template) anywhere you'd like.
After the promise chain is resolved (after success), Angular will run a digest cycle and rebind everything on $scope.
Try
$scope.getRequestDigest = function () {
var url = urlParams['SPAppWebUrl'] + '/_api/contextinfo';
return $http.post(url);
}
var digestPromise = $scope.getRequestDigest();
digestPromise.then(function(response){
console.log(response.data);
});
This way you are actually returning a promise, which AngularJS implements through the $q service.
If you were to output (console.log(digestPromise)) digestPromise, you will see that you can all sorts of functions on it, like success or complete, for example.
You could use chain promise using .then
$scope.getRequestDigest = function () {
var url = urlParams['SPAppWebUrl'] + '/_api/contextinfo';
return $http.post(url) //this will return a promise
.then(function (res) {
return res.data; //on success this will return a data to caller function
});
}
Then the caller function will have call the function and get the data like this
$scope.getRequestDigest().then(function(data){
console.log(data)
//here you can get data returned from `getRequestDigest` method
})

Categories