1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

update promise & message handling

This commit is contained in:
Hiroyasu Nishiyama 2020-04-10 23:06:43 +09:00
parent 161f6090c1
commit c649e1b4a2

View File

@ -87,17 +87,6 @@ module.exports = function(RED) {
} }
} }
function processAsyncResult(result, callbacks) {
var promises = callbacks;
if (Array.isArray(result)) {
promises = promises.concat(result);
}
else if(result) {
promises = promises.concat([result]);
}
return Promise.all(promises);
}
function FunctionNode(n) { function FunctionNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
var node = this; var node = this;
@ -108,44 +97,6 @@ module.exports = function(RED) {
var handleNodeDoneCall = true; var handleNodeDoneCall = true;
var callbackPromises = [];
function createAsyncCallback() {
var result = undefined;
var callbacks = undefined;
var promise = new Promise((resolve, reject) => {
if (result) {
if (result.error) {
reject(result.error);
}
else {
resolve(result.value);
}
}
else {
callbacks = {
resolve: resolve,
reject: reject
};
}
});
var cb = function(err, val) {
if (callbacks) {
if (err) {
callbacks.reject(err);
}
else {
callbacks.resolve(val);
}
}
else {
result = { error: err, value: val };
}
};
callbackPromises.push(promise);
return cb;
}
// Check to see if the Function appears to call `node.done()`. If so, // Check to see if the Function appears to call `node.done()`. If so,
// we will assume it is well written and does actually call node.done(). // we will assume it is well written and does actually call node.done().
// Otherwise, we will call node.done() after the function returns regardless. // Otherwise, we will call node.done() after the function returns regardless.
@ -171,13 +122,14 @@ module.exports = function(RED) {
"};\n"+ "};\n"+
node.func+"\n"+ node.func+"\n"+
"})(msg,send,done);"; "})(msg,send,done);";
var iniText = "(function () {\n"+node.ini +"\n})();"; var iniText = "(async function () {\n"+node.ini +"\n})();";
var finText = "(function () {\n"+node.fin +"\n})();"; var finText = "(function () {\n"+node.fin +"\n})();";
var finScript = null; var finScript = null;
var finOpt = null; var finOpt = null;
node.topic = n.topic; node.topic = n.topic;
node.outstandingTimers = []; node.outstandingTimers = [];
node.outstandingIntervals = []; node.outstandingIntervals = [];
var initValue = undefined;
var sandbox = { var sandbox = {
console:console, console:console,
util:util, util:util,
@ -305,8 +257,9 @@ module.exports = function(RED) {
node.outstandingIntervals.splice(index,1); node.outstandingIntervals.splice(index,1);
} }
}, },
promisify: (util.hasOwnProperty("promisify") ? util.promisify : undefined), getInitValue: function() {
asyncCallback: createAsyncCallback return initValue;
}
}; };
if (util.hasOwnProperty('promisify')) { if (util.hasOwnProperty('promisify')) {
sandbox.setTimeout[util.promisify.custom] = function(after, value) { sandbox.setTimeout[util.promisify.custom] = function(after, value) {
@ -314,6 +267,7 @@ module.exports = function(RED) {
sandbox.setTimeout(function(){ resolve(value); }, after); sandbox.setTimeout(function(){ resolve(value); }, after);
}); });
}; };
sandbox.promisify = util.promisify;
} }
var context = vm.createContext(sandbox); var context = vm.createContext(sandbox);
try { try {
@ -330,13 +284,10 @@ module.exports = function(RED) {
} }
var promise = Promise.resolve(); var promise = Promise.resolve();
if (iniScript) { if (iniScript) {
var result = vm.runInContext(iniText, context, iniOpt); promise = iniScript.runInContext(context, iniOpt);
if (result || callbackPromises) {
promise = processAsyncResult(result, callbackPromises);
} }
}
promise.then(function (v) { function processMessage(msg, send, done) {
node.on("input", function(msg,send,done) {
try { try {
var start = process.hrtime(); var start = process.hrtime();
context.msg = msg; context.msg = msg;
@ -394,6 +345,21 @@ module.exports = function(RED) {
done(JSON.stringify(err)); done(JSON.stringify(err));
} }
} }
}
const RESOLVING = 0;
const RESOLVED = 1;
const ERROR = 2;
var state = RESOLVING;
var messages = [];
node.on("input", function(msg,send,done) {
if(state === RESOLVING) {
messages.push({msg:msg, send:send, done:done});
}
else if(state === RESOLVED) {
processMessage(msg, send, done);
}
}); });
node.on("close", function() { node.on("close", function() {
if (finScript) { if (finScript) {
@ -412,9 +378,25 @@ module.exports = function(RED) {
} }
node.status({}); node.status({});
}); });
promise.then(function (v) {
initValue = v;
var msgs = messages;
messages = [];
while (msgs.length > 0) {
msgs.forEach(function (s) {
processMessage(s.msg, s.send, s.done);
});
msgs = messages;
messages = [];
}
state = RESOLVED;
}).catch((error) => { }).catch((error) => {
messages = [];
state = ERROR;
node.error(error); node.error(error);
}); });
} }
catch(err) { catch(err) {
// eg SyntaxError - which v8 doesn't include line number information // eg SyntaxError - which v8 doesn't include line number information
@ -426,3 +408,4 @@ module.exports = function(RED) {
RED.nodes.registerType("function",FunctionNode); RED.nodes.registerType("function",FunctionNode);
RED.library.register("functions"); RED.library.register("functions");
}; };