Every time I attempt to execute this piece of code in "node.js", an error pops up

const express = require('express');
const request = require('request');
const bodyParser = require('body-parser');
const https = require('https');
const app = express();

app.use(express.static('public'));
app.use(bodyParser.urlencoded({extended: true}));
app.get('/', function(req, res){
  res.sendFile(__dirname + "/signup.html");
});
app.post('/', function(req,res){
  const firstName = req.body.fName;
  const lastName = req.body.lName;
  const email = req.body.email;
  const data = {
    members: [
      {
        email_address:  email,
        status: "subscribed",
        merge_fields: {
          FNAME: firstName,
          LNAME: lastName
        }
      } 
    ]
  };

  const jsonData = JSON.stringify(data);
  const url ="https://us18.api.mailchimp.com/3.0/lists/081d03d860";
  const options ={
    method: "POST",
    auth: "mick:2c775770a96a720b8c492df7974840d3-us18"
  }

  const apiRequest = https.request(url, options, function(response) {
    if (response.statusCode === 200){
      response.send('Successfully subscribed');
    } else {
      response.send('There was an error with signing up, please try again');
    }

    response.on('data', function(data){
      console.log(JSON.parse(data));
    });
  });

  apiRequest.write(jsonData);
  apiRequest.end();
});

app.listen(3000, function(){
  console.log('Server is running on port 3000');
});

I am working on a project using Node.js to create a newsletter sign up page that interacts with the MailChimp API. However, when I run my code in Node.js, I keep encountering the following error message. It appears that there is an issue with the event listener argument not being a function. Can someone assist me with resolving this problem?

TypeError: "listener" argument must be a function
    at ClientRequest.once (events.js:340:11)
    at new ClientRequest (_http_client.js:164:10)
    at Object.request (http.js:38:10)
    at Object.request (https.js:239:15)
    at C:\Users\Desmond\Desktop\Web Development\Newsletter-Singup\app.js:40:24
    at Layer.handle [as handle_request] (C:\Users\Desmond\Desktop\Web Development\Newsletter-Singup\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\Desmond\Desktop\Web Development\Newsletter-Singup\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\Users\Desmond\Desktop\Web Development\Newsletter-Singup\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\Users\Desmond\Desktop\Web Development\Newsletter-Singup\node_modules\express\lib\router\layer.js:95:5)
    at C:\Users\Desmond\Desktop\Web Development\Newsletter-Singup\node_modules\express\lib\router\index.js:281:22

Answer №1

While reviewing the documentation for the 'https' module, I noticed that the two available arguments are:

  • request(url, options)
  • request(options, callback)

Would you consider updating your code to reflect this format?

app.post('/', function(req, res) {
    const firstName = req.body.fName;
    const lastName = req.body.lName;
    const email = req.body.email;

    const data = {
        members: [{
                email_address: email,
                status: "subscribed",
                merge_fields: {
                    FNAME: firstName,
                    LNAME: lastName
                }
            }
        ]
    };

    const jsonData = JSON.stringify(data);

    const options = {
        hostname: 'us18.api.mailchimp.com',
        path: "/3.0/lists/081d03d860",
        method: "POST",
        auth: "mick:2c775770a96a720b8c492df7974840d3-us18"
    }

    const request = https.request(options, function(response) {
        if (response.statusCode === 200) {
            response.send('Successfully subscribed');

        } else {
            response.send('There was an error with signing up, please try again');
        }

        response.on('data', function(data) {
            console.log(JSON.parse(data));
        });
    });

    request.write(jsonData); 
    request.end();
});

Answer №2

When looking at this snippet:

app.post('/', function(req, res) {    // <== Note that the response is named res

You encounter this piece of code:

const request = https.request(options, function(response) {
    if (response.statusCode === 200) {
        response.send('Successfully subscribed');     // <== This part attempts to send a 
                                                      // response to your response which 
                                                      // doesn't add up

    } else {
        response.send('There was an error with signing up, please try again');
    }

The logic in this code seems flawed. You shouldn't invoke response.send() on the http.request response immediately after receiving it. The http request has completed - you made a request and got a response.

Possibly, you intended for that code block to appear like this where you are sending a response from your server back to the original client's request:

const request = https.request(options, function(response) {
    if (response.statusCode === 200) {
        res.send('Successfully subscribed');    // <== here, use res instead to reference
                                                // the response to the original Express
                                                // request/response

    } else {
        res.send('There was an error with signing up, please try again');
    }

Just so you know, the request() library has been deprecated and is not recommended for new code. There are alternative libraries available, you can find some good options here. Personally, I prefer using got() as it is easy to use, fully supports promises (the modern way of handling asynchronous code), and includes all necessary features.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Parsing JSON data into Excel format using Node.js

As I attempt to transform a large amount of JSON data into an Excel file, I have tested out a few modules. Here are my observations - if anyone knows of a more efficient node module that can handle larger amounts of data, please share so I can further inve ...

Transferring information from jQuery to AngularJS controller

Is there a way to transfer data generated by jQuery into an AngularJS controller? <textarea ng-click="showSelectedText(selection.text)" name="editor1" id="editor1" cols="118" rows="35"> Using jQuery to collect data: $( "#editor1" ).select(funct ...

Access the Node Server through the phone browser

Currently, I am in search of a node middleware that can inform cellphones about my app being a captive portal. All requests are directed to the Node/Express server IP using iptables rules and the app is functioning perfectly. However, there seems to be an ...

Vue.js has a feature where it automatically closes the form tag within a for loop

In my Vue.js application, I have created a table where each row is a form with a submit button. This is the code snippet I am using: <div id="admin-user"> <table class="table"> <tr v-for="(user, index) in users"> < ...

Wildcard GET requests in Express cause routing issues when navigating to a React application

My project is derived from the React-Webpack boilerplate repository found at this link: (https://github.com/wallacyyy/webpack-heroku/blob/master/server.js). Initially, everything was working fine but now I want to add routing within my React application. T ...

The error message "TextEncoder is not defined with mongodb nodes" is indicating that there is

Encountering an issue while running jest test cases: Getting the error message - ReferenceError: TextEncoder is not defined. Current Node version being used is 14.18.0. Mongodb NPM package version is 4.1.3. Typescript version installed is 4.4.3. Here ...

Different ways to conditionally set the expanded prop for the Material UI TreeView component

I am currently working on implementing a tree select feature similar to the one found in antd's tree-select using material ui components. Specifically, I have a TextField and TreeView components from Material-UI stacked vertically. Initially, I want t ...

Change the space character ' ' to '-' when a key is lifted

Hey, I need some help with a coding problem. I have two input fields and I want to automatically mirror the text from the first input into the second input field using a keyup jquery function. However, my current setup adds a space whenever I hit the spac ...

The presence of Bootstrap remains hidden unless space is designated for it

Question about Bootstrap 5.1.3: Is there a way to hide elements on a page using the bootstrap class ".invisible" without allocating space for them? Currently, when the elements are set to visible using the class ".visible", they occupy space on the page ...

The instance is referencing "underscore" during render, but it is not defined as a property or method

I have experience as a skilled react developer, but I've taken over a vue.js project from another developer and managed it for quite some time. Regrettably, I haven't put in the effort to learn vue properly. When using lodash, I encountered an u ...

Unable to loop through the "dataList" retrieved from a service call to the java backend within an Angular 9 application

After receiving JSON data from a Java backend service called houseguidelines, the information is sent to an Angular application via a service call. I am attempting to iterate over this returned JSON data and add it to an array I have created. Unfortunately ...

Using HTML5 canvas to draw circles with additional metadata stored in variables

I'm designing a seating chart that will indicate spots with circles and show a tooltip on mouseover with the person's first name, last name, and possibly other details. I plan to use Kinetic.JS for region/tooltip support based on the tutorials I& ...

Creating dynamic links within HTML through real-time updating

In my application, I have a feature that generates a list of words and converts them into clickable links. When the user clicks on a link, I want to extract the {{word.name}} from the HTML link without navigating to a new page. I simply need to retrieve th ...

Encountering an issue when attempting to execute the Jenkins job for running Cypress automation tests: The cypress npm library has been successfully installed, yet the Cypress binary file

Encountered an error while executing the Jenkins job integrated for Cypress test cases. Running as SYSTEM Building in workspace C:\Users\Gaurav\CypressAutomation [CypressAutomation] $ cmd /c call C:\Windows\TEMP\jenkins1604066 ...

I am having trouble with my jQuery login function not properly connecting to the PHP file

Hey there, I've been working on creating a login system from scratch by following an online tutorial. The initial Javascript is functioning properly as it detects errors when the inputs are empty. However, once I enter text into the input fields and c ...

What is the reason behind Visual Studio intellisense not displaying the methods of XMLHttpRequest objects?

Why am I unable to access the open and send methods of the XMLHttpRequest object in Visual Studio's Intellisense? var httprequest = new XMLHttpRequest(); httprequest. I cannot see the methods in Intellisense after the dot. ...

Creating a Button with Icon and Text in TypeScript: A step-by-step guide

I attempted to create a button with both text and an icon. Initially, I tried doing it in HTML. <button> <img src="img/favicon.png" alt="Image" width="30px" height="30px" > Button Text ...

What could be causing my if-else statement to malfunction in JavaScript?

I'm working on a form where certain conditions need to be met based on the selected order type. For instance, if a market order is chosen, the stop price and limit price should default to zero and become read-only fields. Similarly, selecting a limit ...

switching from grunt's autoprefixer to grunt's postcss

Since grunt-autoprefixer has been deprecated, I am looking to transition to grunt-postcss. Being new to the world of grunt and its dependencies, I couldn't find clear instructions in the documentation for this migration process. To complete the migr ...

Sending a list of data using ajax to an external PHP script for deferred rendering in datatables

I've set up a form on one of my pages that features check boxes linked to the primary id of certain information that is retrieved on another page based on whether the check box was checked or not. After switching to jquery-datatables with deferred ren ...