Port P4JsApi code
Let’s start with a simple P4JSAPI program. This program runs p4 info and displays the ‘set of name/value pairs’ result in an HTML table:
---- jsapi/serverinfo.html <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Server Info</title> <style> body { font:normal 12px serif; } .nameFont { color:DarkGray; } </style> <script type="text/javascript"> function runOnload() { try { var serverName = P4JsApi.getPort(); // Run the p4 info command. var serverInfo = P4JsApi.p4(' -p ' + serverName + ' info'); // Populate server info into table var serverInfoTable = document.getElementById("serverInfoTable"); var index = 0; for (var key in serverInfo.data[0]) { var row = serverInfoTable.insertRow(index++); // left cell var cellLeft = row.insertCell(0); var textNode = document.createTextNode(key); cellLeft.appendChild(textNode); cellLeft.setAttribute("class", "nameFont"); // right cell var cellRight = row.insertCell(1); textNode = document.createTextNode( serverInfo.data[0][key]); cellRight.appendChild(textNode); } } catch(e) { alert(e); } } </script> </head> <body onload="runOnload();"> <table id="serverInfoTable"></table> </body> </html> ---- end of - jsapi/serverinfo.html
This is a synchronous implementation. P4JsApi.p4(' -p ' + serverName + ' info') waits for the result to come back and assigns it to var serverInfo. The code then continues loading the serverInfoTable.
The P4VJS implementation looks slightly different:
---- p4vjs/serverinfo1.html
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8" /> <title>Server Info</title>
<style>
body {
font:normal 12px serif;
}
</style>
<script src="./p4vjs.js"></script>
<script type="text/javascript">
async function runOnload() {
try {
var serverInfo = await p4vjs.p4('info');
var serverInfoTable = document.getElementById("serverInfoTable");
var index = 0;
for (var key in serverInfo.data[0]) {
var row = serverInfoTable.insertRow(index++);
// left cell
var cellLeft = row.insertCell(0);
var textNode = document.createTextNode(key);
cellLeft.appendChild(textNode);
cellLeft.setAttribute("class", "nameFont");
// right cell
var cellRight = row.insertCell(1);
textNode = document.createTextNode(
serverInfo.data[0][key]);
cellRight.appendChild(textNode);
}
} catch(e) {
alert(e);
}
}
</script>
</head>
<body onload="runOnload();">
<table id="serverInfoTable"></table>
</body>
</html>
---- end of – p4vjs/serverinfo1.html
P4VJS commands are implemented in <script src="./p4vjs.js"></script>
. This file needs to be included to support P4VJS commands.
P4VJS commands all implement a JavaScript Promise. To get synchronous behavior using a Promise, you need to use a an async/await
pair. To allow a function to be marked as await, the calling function has to be marked as async
.
async function runOnload() { … }
Marking a function as async has the following effects:
- The function now returns a Promise (you changed its return value).
- The function allows synchronous method calling (you can use
await
in the function).
await
calls p4vjs.p4(…)
and waits for the result:
var serverInfo = await p4vjs.p4('info');
Changing the same program to an asynchronous implementation looks like this:
---- p4vjs/serverinfo2.html <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Server Info</title> <style> body { font:normal 16px verdana; } </style> <script src="./p4vjs.js"></script> <script type="text/javascript"> function runOnload() { try { // Populate server info into table var serverInfoTable = document.getElementById("serverInfoTable"); p4vjs.p4('info').then(function(serverInfo) { var index = 0; for (var key in serverInfo.data[0]) { var row = serverInfoTable.insertRow(index++); // left cell var cellLeft = row.insertCell(0); var textNode = document.createTextNode(key); cellLeft.appendChild(textNode); // right cell var cellRight = row.insertCell(1); textNode = document.createTextNode( serverInfo.data[0][key]); cellRight.appendChild(textNode); } }); } catch(e) { alert(e); } } </script> </head> <body onload="runOnload();"> <table id="serverInfoTable"></table> </body> </html> ---- end of – p4vjs/serverinfo2.html
Since p4vjs.p4('info')
is implemented as a Promise, the .then()
operator can be called to chain the result of the Promise to an inline function. This implementation does not wait; runOnLoad(..)
returns before the response of p4vjs.p4('info')
has been received. The inline .then(function(serverInfo) {..}
is called when the P4VJS function returns a value.
The syntax:
p4vjs.p4('info').then(function(serverInfo) { … }
p4vjs.p4(…, …)
takes a third parameter that can be used to pass in a named callback function instead of an anonymous inline function.
---- p4vjs/serverinfo3.html <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Server Info</title> <style> body { font:normal 16px verdana; } .nameFont { font-weight:bold; color:DarkGray; } </style> <script src="./p4vjs.js"></script> <script type="text/javascript"> function runOnload() { try { // Populate server info into table var serverInfoTable = document.getElementById("serverInfoTable"); var loadcallback = loadData; p4vjs.p4('info', '', loadcallback); } catch(e) { alert(e); } } function loadData(serverInfo) { console.log("p4 info called", serverInfo); var index = 0; for (var key in serverInfo.data[0]) { var row = serverInfoTable.insertRow(index++); // left cell var cellLeft = row.insertCell(0); var textNode = document.createTextNode(key); cellLeft.appendChild(textNode); cellLeft.setAttribute("class", "nameFont"); // right cell var cellRight = row.insertCell(1); textNode = document.createTextNode( serverInfo.data[0][key]); cellRight.appendChild(textNode); } } </script> </head> <body onload="runOnload();"> <table id="serverInfoTable"></table> </body> </html> |---- end of – p4vjs/serverinfo3.html
The syntax:
var loadcallback = loadData; p4vjs.p4('info', '', loadcallback);
The third parameter has to be a variable that references a function. p4vjs.p4(…)
is the only function that supports a callback parameter.