How to execute JavaScript in a Task

Execute JavaScript in the Producer makes BitSky be more powerful and flexible, for now, only Headless Producer can execute JavaScript.

Task with JavaScript

A Task is a contract that both Retailer, Supplier, and Producer can understand, so to execute JavaScript in a Task, you need to include JavaScript Code string inside the Task(metadata.script). Currently, only Headless Producer support execute JavaScript. To make sure Headless Producer can execute your JavaScript correctly, all your JavaScript should be put inside an async function like this:
async function customFunction() {
// Add your code inside
Inside customFunction, you have four global variables, and those four variables are ONLY readable, if you try to change it, it will throw a JavaScript exception and cause your Task to fail.
  1. 1.
    $$page: Puppeteer page instance, refer to the current page
  2. 2.
    $$task: Task information
  3. 3.
    $$_: Lodash instance
  4. 4.
    $$logger: Winston Logger, you can add logs, and you can view the log inside the corresponding Producer(the Producer that execute this Task), this is useful to debug purpose
Except for those four global variables, you also can use require to require NodeJS native modules.
If the return value of customFunction isn't undefined or null, then return value will be set todataset and send back to your Retailer. If you return undefined or null or don't return any value, then will send the whole page back to your Retailer.
In Headless Producer, customFunction is evaluated as Puppeteer Code, so you CANNOT directly evaluate Web APIs, you need to use $$page.execute to evaluate Web APIs
How to convert the JavaScript Function to JavaScript Code String?
For NodeJS, you can simply usecustomFunction.toString(), this will return the JavaScript Code String.
For other languages(Python, Java), a simple way is using tools to compress JavaScript function to a JavaScript Code String


The following examples are based on BitSky Desktop Application, make sure you finished Quick Start before continue.
Use the following customFunction to overwrite customFunction inside Hello Retailer

Waiting for the given number of seconds

A simple use case is before crawling data, pause script execution for several seconds.
async function customFunction() {
await $$page.waitForTimeout(5 * 1000);
This customFunction will pause script execution 5 seconds. And since it doesn't return any value, so Headless Producer will send page HTML back to Retailer.
Except waiting for seconds, you also can wait for Selector, XPath, Function. Please check the following APIs:

Evaluate Web APIs

async function customFunction() {
.querySelector("body div")
`<div id='injected-notification'
style='position: absolute;
top: 100px;
left: 40%;
border: 1px solid #ffccc7;
padding: 50px;
font-size: 24px;
background: #fff2f0;'>
<b>Hello World! -- injected by JavaScript</b>
await $$page.waitFor(5 * 1000);
This customFunction will insert a notification to the current page, and pause 5 seconds.
You can use $$page.evaluate to evaluate Web APIs. Except $$page.evaluate you also can take a look following functions: