NodeJS Express Module Error: TypeError: Cannot read property ‘finished’ of undefined

I’m trying to make an api that gets the text from a site from whatever words you put. I used selenium to load the site up and send the text but I can’t send it back. Here’s my code:

app.get("/search/:data", function(req, res){
async function extraction(){
    driver.findElement(By.xpath("(//input[@type='text'])[6]")).clear();
    driver.findElement(By.xpath("(//input[@type='text'])[6]")).sendKeys(req.params.data.replaceAll('_', ' '));
    console.log(`Sent keys ${req.params.data} from ${req.ip}.`);
    setTimeout(function () {
            driver.findElement(By.xpath("/html/body/div[8]/div[1]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[2]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[3]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[4]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[5]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[6]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[7]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[8]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[9]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[10]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[11]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[12]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[13]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[14]/div")).getText().then(res.write);
            driver.findElement(By.xpath("/html/body/div[8]/div[15]/div")).getText().then(res.write);
            res.end();
        }, 10000);

}
extraction();
});

When I replace res.write with console.log it logs it but I just can’t get it to send. I’m new to Javascript so I’m still learning, I have spent hours searching for an answer but can’t get it to work.

Error message:

  if (msg.finished) {
          ^

TypeError: Cannot read property 'finished' of undefined
    at write_ (node:_http_outgoing:727:11)
    at write (node:_http_outgoing:687:15)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)```

Answer

It seems that you can’t pass res.write as callback, because it looses track of the response object, where it tries to read the finished property from.

Try by creating a custom callback that calls res.write, e.g.

const writeToResponse = res.write.bind(res);

driver.findElement(By.xpath("/html/body/div[8]/div[1]/div")).getText().then(writeToResponse);
// similarly the rest of the code

Apart from the above fix, I see more potential problems with the code in current structure: As far as I remember, .getText returns a promise, so we’re dealing with asynchronous code here.

  1. You’re calling res.end() without waiting for the preceding instructions to finish. This will most likely lead to following error
Error [ERR_STREAM_WRITE_AFTER_END]: write after end

You should probably await each call or all together using Promise.all

  1. If order in which texts are written to the response is important, then you should await each call before executing the next, otherwise all 15 calls execute in parallel and race with writing data to response.

Leave a Reply

Your email address will not be published. Required fields are marked *