How tp send big Data set from loopback.js remote method - loopbackjs

I am reading oracle ref Cursor and storing in p_ref out param and using the streams from resultset.toquerystream() method I am reading the data and pushing the data in array variable and once reached end of the stream I am sending the data.
its working fine for small data set of 1000 records but failing with error ERR_EMPTY_RESPONSE as you can see I am storing the data in array and returning the data once we reach end
but its failing with "ERR_EMPTY_RESPONSE"
oracledb.getConnection(
ds.settings,
function (err, connection) {
if (err) {
cb(err.message, []);
return;
}
let count = 0;
let params = {
p_ref: {type: oracledb.CURSOR, dir: oracledb.BIND_OUT}
};
let cursor = null;
let queryStream = null;
let data = [];
connection.execute(
sql,
params,
{outFormat: oracledb.OBJECT},
function (err, result) {
if (err) {
cb(err.message, []);
doRelease(connection);
return;
}
cursor = result.outBinds.p_ref;
queryStream = cursor.toQueryStream();
queryStream.on('data', function (row) {
count++;
data.push(row);
});
queryStream.on('error', function (err) {
if (!cbCalled) {
cbCalled = true;
cb(err.message);
doRelease(connection);
}
});
queryStream.on('end', function () {
console.log('Rows selected: ' + count);
cb('', data);
doRelease(connection);
});
queryStream.on('close', function () {
if (!cbCalled) {
console.log(count);
doRelease(connection);
}
});
}
);
}
);
Reference from here https://github.com/oracle/node-oracledb/blob/master/doc/api.md
var stream = connection.queryStream('SELECT employees_name FROM employees');
stream.on('error', function (error) { // handle any error... });
stream.on('data', function (data) { // handle data row... });
stream.on('end', function () { // release connection... });
stream.on('metadata', function (metadata) { // access metadata of query });

Try removing the call to doRelease() from the 'end' event.

Related

Cannot determine what is wrong with this action. Input Parameter is null

Using the following results in a null input error. Through debugging the plugin the input parameter is not being passed. Any ideas? I've done hundreds of these but never seen this type of issue.
tdn_GetFoxhoundNotesRequest = function (contactId) {
this.ContactId = contactId;
};
tdn_GetFoxhoundNotesRequest.prototype.getMetadata = function () {
return {
boundParameter: null,
parameterTypes: {
"ContactId": {
"typeName": "Edm.String",
"structurualProperty": 1
}
},
operationType: 0,
operationName: "tdn_GetFoxhoundNotes"
};
};
function LoadNotes(executionContext) {
var formContext = executionContext.getFormContext();
var contactId = formContext.data.entity.getId().replace("{", "").replace("}", "");
var request = new tdn_GetFoxhoundNotesRequest(contactId);
Xrm.WebApi.online.execute(request).then(
function success(result) {
if (result.ok) {
{
result.json().then(function (response) {
formContext.getAttribute("tdn_foxhoundnotestextblob").setValue(response.Notes);
formContext.getAttribute("tdn_foxhoundnotestextblob").setSubmitMode('never');
})
}
}
},
function (error) {
Xrm.Utility.alertDialog(error.message);
});
}

React Native how to get a variable out of an async function and return it

I dont know how to get the variable allP out of this function so i can return it to display on screen.
Ive tried defining the variable outside the function so i could call it in the code but that didnt work. the array prints out in the console log but i just cant seem to get it to show in the return.
sched = async () => {
var i = null;
var getPrice = null;
var allP =[];
try {
const schedinfo = await API.graphql(graphqlOperation(netidget));
this.setState({ schedinfo: schedinfo.data.listLoginModals.items });
for (i = 0; i < schedinfo.data.listLoginModals.items.length; i++) {
getPrice = schedinfo.data.listLoginModals.items[i].Type;
var lowP = await API.graphql(
graphqlOperation(lowest, {
CIndex: getPrice
})
)
if(typeof lowP.data.listlowestprice.items[0] == "undefined") {
lowP = "-";
} else {
lowP = lowP.data.listlowestprice.items[0].Price.toString();
}
if(lowP == " ") {
lowP = "-";
}
allP.push(lowP);
}
console.log(allP);
{this.state.lowprices.map(da => (
<View item={da} key={da.id}>
<Text>{da.Price}</Text>
console.log(da.Price)
</View>
))}
console.log(schedinfo.data.listLoginModals.items.length)
} catch (err) {
console.log('error creating restaurant...', err);
}
};
I want to be able to display the allP array that gets created from the function. Please any help is appreciated thank you so much
Move your code inside of your try sentence to a new async fuction, return it and receive that value on your allP variable (without arrow functions), so:
constructor(){
super();
this.getAllP = this.getAllP.bind(this);
this.sched = this.sched.bind(this);
}
async getAllP() {
try {
....
operations
....
return allP
}
}
async sched() {
var allP = await getAllP();
}

My async call is returning before list is populated in forEach loop

I have a routine which gets a list of filenames from the device, then reads the file(s) to build a list. However, the calling routine always returns with zero items. I print the filenames, so I know they exist, however, it appears that the async is returning before I read the files. I used similar code when making an HTTP call. But, something here is causing the routine to return the list even though it hasn't completed. Perhaps, it is possible that I am calling it at the wrong time? I am calling retrieveItems here:
#override
void initState() {
super.initState();
retrieveItems();
}
Eventually I will have a refresh button, but for now I'd simply like the list to populate with the data from the files...
--------------------
Callee
Future<List<String>> readHeaderData() async {
List<String> l = new List();
List<String> files = await readHeaders(); // Gets filenames
files.forEach((filename) async {
final file = await File(filename);
String contents = await file.readAsString();
User usr = User.fromJson(json.decode(contents));
String name = usr.NameLast + ", " + usr.NameFirst;
print(name);
l.add(name);
}
return l;
Caller
void retrieveItems() async {
LocalStorage storage = new LocalStorage();
await storage.readHeaderData().then((item) {
try {
if ((item != null ) &&(item.length >= 1)) {
setState(() {
users.clear();
_users.addAll(item);
});
} else {
setState(() {
_users.clear();
final snackbar = new SnackBar(
content: new Text('No users found.'),
);
scaffoldKey.currentState.showSnackBar(snackbar);
});
}
} on FileNotFoundException catch (e) {
print(e.toString()); //For debug only
setState(() {
_users.clear();
});
});
}
});
This code
Future<List<String>> readHeaderData() async {
List<String> l = new List();
List<String> files = await readHeaders(); // Gets filenames
files.forEach((filename) async {
final file = await File(filename);
String contents = await file.readAsString();
User user = User.fromJson(json.decode(contents));
String name = user.NameLast + ", " + user.NameFirst;
print(name);
l.add(name);
}
return l;
}
returns the list l and then processes the asyc forEach(...) callbacks
If you change it to
Future<List<String>> readHeaderData() async {
List<String> l = new List();
List<String> files = await readHeaders(); // Gets filenames
for(var filename in files) { /// <<<<==== changed line
final file = await File(filename);
String contents = await file.readAsString();
User user = User.fromJson(json.decode(contents));
String name = user.NameLast + ", " + user.NameFirst;
print(name);
l.add(name);
}
return l;
}
the function will not return before all filenames are processed.
files.forEach((filename) async {
means that you can use await inside the callback, but forEach doesn't care about what (filename) async {...} returns.
Also possible
await Future.forEach(yourList, (T elem) async { ...async staff });
To expand on Günter's comment regarding using list.map(f), here's an example of converting a forEach call so that it works correctly.
Broken example
Incorrectly assumes forEach will wait on futures:
Future<void> brokenExample(List<String> someInput) async {
List<String> results;
someInput.forEach((input) async {
String result = await doSomethingAsync(input);
results.add(result);
});
return results;
}
Corrected example
Waits on the async functions to complete, using Future.wait and .map():
Future<void> correctedExample(List<String> someInput) async {
List<String> results;
await Future.wait(someInput.map((input) async {
String result = await doSomethingAsync(input);
results.add(result);
}));
return results;
}
I encountered the similar issue. The problem is that dart will NOT wait for "forEach" contrary to public believe. There are two solutions:
1) Convert forEach to for loop as indicated by others. Another is use Future:
2) await Future.forEach(list, (item) async {
// your code
final result = await getMyResult();
});
Another option
Future.wait(someList.map((item) => something_returns_future(item)));

nokia here maps geocoding and display map

please, could someone explain me how can I manage, in Here Maps code, nokia.maps.map.Display listener and nokia.places.search.manager.geocode method?
I have markers to be geocoded, in geocode "oncomplete" it waits for the request to be completed, after that it listens when map display is ready, so as it happens asynchronously, it sometimes displays on browser a map not finished yet, this is because map.zoomTo(bbox, false) was not executed.
How can I manage these two events?
<script type="text/javascript">
function goPageOnLoad() {
container = new nokia.maps.map.Container();
map = new nokia.maps.map.Display(document.getElementById('gmapcanvas'),
{ components:[ infoBubbles, new nokia.maps.map.component.Behavior(), new
nokia.maps.map.component.ZoomBar(), new
nokia.maps.map.component.Overview(), new
nokia.maps.map.component.TypeSelector(), new
nokia.maps.map.component.ScaleBar() ] });
addMarkersGeoLoc(map,container);
}
function addMarkersGeoLoc(map,container) {
countMarkerGeoLoc=1; coordinate = new
nokia.maps.geo.Coordinate(0, 0); startGeoCode('Via Roma 2, 16038 Santa
Margherita Ligure GE ');
}
function startGeoCode(addressStringt) {
nokia.places.search.manager.geoCode({
searchTerm : addressString,
onComplete: function(data, requestStatus){
if(data != null){
coordinate =
new nokia.maps.geo.Coordinate(data.location.position.latitude,
data.location.position.longitude);
var marker = new
nokia.maps.map.StandardMarker(coordinate, {brush: {color: "#FF0000"}});
marker.addListener( CLICK, function (evt) {
infoBubbles.openBubble(content, marker.coordinate); } );
container.objects.add(marker);
managersFinished++;
}
else {
managersFinished++; alert('Address: '+addressString+', is not
localizable.');
}
if(managersFinished === countMarkerGeoLoc) {
map.objects.add(container);
map.set('zoomLevel', 14);
map.addListener("displayready", function () {
map.set('center',
[40.645304, 14.874063]);
bbox = container.getBoundingBox();
if(bbox !=null){
map.zoomTo(bbox, false);
}
});
}
}
});
}
</script>
The simplest method would be to wait for the displayready event before starting your geocoding.
function goPageOnLoad() {
container = new nokia.maps.map.Container();
map = new nokia.maps.map.Display
.. etc...
map.addListener('displayready', function () {
addMarkersGeoLoc(map,container);
}, false);
The other alternative would be to have a global bbox variable and use zoomTo() twice - either on displayready or on managersFinished === countMarkerGeoLoc i.e.
var bbox;
...
function goPageOnLoad() {
container = new nokia.maps.map.Container();
map = new nokia.maps.map.Display
.. etc...
map.addListener("displayready", function () {
if(bbox){map.zoomTo(bbox, false);}
});
...
if(managersFinished === countMarkerGeoLoc) {
map.objects.add(container);
bbox = container.getBoundingBox();
map.zoomTo(bbox, false);
Either the first or the second of the zoomTo() functions must fire to move the map.

What's the best way to process array of JSON messages posted to Nodejs server?

A client sends an array of JSON messages to be stored at Nodejs server; but client will require some sort of acknowledgement for each message (through unique id), that it was properly stored at server, and hence doesn't need to be sent again.
At server I want to parse the JSON array, then loop through it, store each message in db, store response for this message in JSON array named responses, and finally send this responses array to the client. But as the db operations are async, all other code is executed before any result returned from db storing methods. My question is how to keep updating the responses array, untill all db operations are complete?
var message = require('./models/message');
var async = require('async');
var VALID_MESSAGE = 200;
var INVALID_MESSAGE = 400;
var SERVER_ERROR = 500;
function processMessage(passedMessage, callback) {
var msg = null;
var err = null;
var responses = [];
isValidMessage(passedMessage, function(err, result) {
if(err) {
callback( createResponse(INVALID_MESSAGE, 0) );
}else{
var keys = Object.keys(result);
for(var i=0, len = keys.length; i<len; i++) {
async.waterfall([
//store valid json message(s)
function storeMessage(callback) {
(function(oneMessage) {
message.processMessage(result[i], function(res) {
callback(res, result[i].mid, callback);
});
})(result[i]);
console.log('callback returns from storeMessage()');
},
//create a json response to send back to client
function createResponse(responseCode, mid, callback) {
var status = "";
var msg = "";
switch(responseCode) {
case VALID_MESSAGE: {
status = "pass";
msg = "Message stored successfuly.";
break;
}
case INVALID_MESSAGE: {
status = "fail";
msg = "Message invalid, please send again with correct data.";
break;
}
case SERVER_ERROR: {
status = "fail";
msg = "Internal Server Error! please contact the administrator.";
break;
}
default: {
responseCode = SERVER_ERROR;
status = "fail";
msg = "Internal Server Error! please contact the administrator.";
break;
}
}
var response = { "mid": mid, "status": status, "message": msg, "code": responseCode};
callback(null, response );
}
],
function(err, result) {
console.log('final callback in series: ', result);
responses.push(result);
});
}//loop ends
}//else ends
console.log('now we can send response back to app as: ', responses);
});//isValid finishes
}
To expand on what lanzz said, this is a pretty common solution (start a number of "tasks" all at the same time, and then use a common callback to determine when they're all done). Here's a quick paste of my function from my userStats function, which gets the number of active users (DAU, WAU, and HAU):
exports.userStats = function(app, callback)
{
var res = {'actives': {}},
day = 1000 * 60 * 60 * 24,
req_model = Request.alloc(app).model,
actives = {'DAU': day, 'MAU': day*31, 'WAU': day*7},
countActives = function(name, time) {
var date = new Date(new Date().getTime() - time);
req_model.distinct('username',{'date': {$gte: date}}, function(e,c){
res.actives[name] = parseInt(c ? c.length : 0, 10);
if(Object.keys(actives).length <= Object.keys(res.actives).length)
callback(null, res);
});
};
var keys = Object.keys(actives);
for(var k in keys)
{
countActives(keys[k], actives[keys[k]]);
}
};
Only send your responses array when the number of items in it equals the number of keys in your result object (i.e. you've gathered responses for all of them). You can check if you're good to send after you push each response in the array.