Как получить результаты асинхронного кода изнутри среды песочницы (vm2)?
Я работал над процессом, где мне нужно запустить несколько скриптов (внутри оболочки) в среде песочницы. Но подвох в том, что внутри этой обертки я буду запускать некоторый js-код (который я рассматриваю как собственную логику), используя eval ().
Чтобы добавить к этому больше, эта пользовательская логика, в свою очередь, содержит некоторые асинхронные манипуляции (выборка данных из mongodb).
Мне нужно выполнить весь этот процесс таким образом, чтобы процесс был синхронизирован и получил ответ в реальной среде (основной процесс), чтобы продолжить нормальный поток приложения, основанный на этом результате.
Примечание: для виртуальной среды я использую модуль VM2
Код настройки:
* Sandbox Script (основная оболочка) - sandboxScript.js
(function() {
console.log("Sandbox Environment");
........
........
var ypAsync = require('async');
const mongoConnector = require(sandboxModulesPath+'/mongo_manipulation_object');
var result = {
status : 0,
body : ''
};
ypAsync.series([function(callback){
console.log("--------- Sandbox Sync1");
//***************************************************
//****** eval() to execute custom logic. ************
//****** (contains fetching details from mongo) *****
//***************************************************
eval(script.userScript);
//***************************************************
//***************************************************
},function(mongoResult,callback){
console.log("--------- Sandbox Sync2");
console.log(result);
result.status = 200;
result.body = mongoResult;
callback(null,ypresponseAccessObj);
}],function(err,finalResult){
console.log("--------- Sandbox final Sync");
console.log(finalResult);
return finalResult;
});
})();
* Пользовательская логика (выполняется внутри eval ()) user.script
var mongoObject= new mongoConnector ('Demo Collection');
mongoObject.select("stmt",function(err,results){
console.log("----- select() callback ------");
console.log(err);
console.log(results); /*Able to get the results*/
if(err){
callback(err);
}
else{
callback(err,results); //Control needs to go to the next series
//block of async.series in sandboxScript.js,
//where eval was called.
//But the results are not transferred*/
}
});
* Конфигурация узла Vm (основной процесс узла) - vmConfig.js
.......
.......
.......
//**** Read Sandbox helper script ****
var helper = fs.readFileSync(__dirname + '/../sandbox/sandboxScript.js', {
encoding: "utf8" });
const {NodeVM, VMScript} = require('vm2');
const vm = new NodeVM({
sandbox: {
sandboxModulesPath : __dirname + '/../sandbox',
request : currentRequestObj,
script: {
userScript: userScript
}
sandbox: {
sandboxModulesPath : __dirname + '/../sandbox',
mongoDB : db, /* Passing Mongo DB instance to sandbox*/
script: {
userScript: userScript
}
},
require: {
context: 'sandbox',
external: ['lodash','async','q'],
builtin: ['url','querystring'],
root: "./"
}
});
try{
console.log("------ Main Process ------");
var result = vm.run("module.exports = "+helper,'vmConfig.js');
console.log(result); /* Result not received*/
callback(null, result);
}
catch(e){
console.log("Sandbox Error");
console.log(e);
callback(null, e.message);
}
.......
.......
.......
* Монго манипуляции - mongo_manipulation_object.js
let async = require('async');
function MongoManipulationObject(collectionName){
console.log("************ In MongoManipulationObject Constructor ");
this.collectionName= collectionName;
this.remoteResponse = {
"result" : []
};
}
MongoManipulationObject.prototype.select = function(statement,callback){
var self = this;
async.waterfall([function(callback){
// Connect to Mongo Collection to access details
let collection = mongoDB.get().collection(self.collectionName);
collection.find().toArray(function(err,documents){
if(err){
callback(err);
}
else{
if(documents == null){
callback(null, "Empty");
}else{
// console.log("Document Details");
callback(null, documents);
}
}
});
}],function(err,finalResult){
// console.log("Final Callback");
if(err){finalResult
console.log(err);
self.remoteResponse = err;
callback(self.remoteResponse);
}
else{
self.remoteResponse.result = finalResult;
callback(null,self.remoteResponse); // send result back to
//select() in Custom Logic (user.script)
}
});
}
module.exports = MongoManipulationObject