I have server side code, I use ES 7 await async function so my code runs in sync fashion, this works great. But now I wanted to have some logging (I write into a mongo API_LOGS collection server side). But this is not allowed, I get the famous ERROR while reloading the new app: [Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.] error.
If I remove the comments it breaks… How to solve this? thank you
//use ES7 await function so this code will run in synchronous mode
return await qsocks.Connect(engineConfig)
.then(function(global) {
// console.log('connected to Qsocks');
_global = global;
return global.openDoc(appId, '', '', '', true) //global.openDoc(appId), this code opens the app without data, that is faster!
})
.then(function(doc) {
console.log('** getAppsViaEngine, QSocks opened and now tries to set the script for appId: ', appId);
return doc.getScript()
.then(function(script) {
console.log('get Script success, ', script);
// var call = {};
// call.action = 'Replace script'
// call.request = 'We extracted the following script from the app: ' + script;
// REST_Log(call);
// if you want to replace the database connection per customer use the script below.
//return doc.setScript(script.replace(scriptMarker, scriptReplace)).then(function (result) {
//you can also change the sense database connection: https://github.com/mindspank/qsocks/blob/master/examples/App/create-dataconnection.js
return doc.setScript(script) //we now just include the old script in this app
.then(function(result) {
ps: QSocks is a NPM module to connect to the qlik sense engine API. (A reporting tool)
my log function is like this
import { Mongo } from 'meteor/mongo';
export const APILogs = new Mongo.Collection('apiLogs');
export function REST_Log(call){
call.createDate = new Date();
call.createdBy = null; //this.userId;
APILogs.insert(call);
}
Yes Thank you. But i thought mongo inserts are synchronous. So without callback, and are meteor side code (not external) so how would an collection.insert look like?
Not sure I understood your question. However, yes insert are synchronous. In my case, I had the same error as you did because when the callback from the api call was fired, I did not bind the environment to the callback.
You can also use Promise.await(…) to make the promise synchronous and then proceed with the insertion.
Key difference here is that I don’t use an external lib and therefore I would think I don’t need any tricks… (I don’t get any error with my mongo insert)
Or does the async await break normal meteor behavior?
qsocks is using a third party Promise library, which will not play nicely with fibers/futures in Meteor, so you will need to use promised Mongo methods. The current MongoDB driver used in Meteor 1.4.1.1 uses Promises natively when used in the non-callback mode. Access to those methods will need to be done via Collection.rawCollection() as you have suggested. Instead of:
export function REST_Log(call){
call.createDate = new Date();
call.createdBy = null; //this.userId;
APILogs.insert(call);
}
You should use something like:
export function REST_Log(call){
call.createDate = new Date();
call.createdBy = null; //this.userId;
return APILogs.rawCollection().insert(call); // return a Promise
}
However, you should check the API docs for insert in case your call is not compatible with the native functionality (you may need to explicitly define a string _id), or you need to amend the options.
That’s a tricky one, because it would have been OK with Meteor’s inbuilt Promises. The “problem” here is there are so many (too many?) Promise libraries in npmland.
Fair point but I came across this headache using native es6 promises. It would save other newbs like me a few strands of hair if it were written down somewhere