request(…).then is not a function error when making a POST request

橙三吉。 提交于 2021-02-05 07:46:16

问题


I'm trying to create a firebase function that makes a HTTP POST request whenever a new document is created.

This is my code:

import * as functions from 'firebase-functions';

const admin = require('firebase-admin');

const request = require("request");


exports.sendMessage = functions.firestore.document('comms/{comms}').onCreate((snap, context) => {


  const newValue = snap.data();

  if (newValue) {

    //const email = newValue.email;
    const msg = newValue.msg;


    return request({
      uri: "url",
      method: 'POST',
      body: msg,
      json: true,
      resolveWithFullResponse: true
    }).then((response: { statusCode: number; }) => {
      if (response.statusCode >= 400) {
        throw new Error(`HTTP Error: ${response.statusCode}`);
      }
      console.log('SUCCESS! Posted', msg);
    });

  }

 return Promise 
});
Error received:

TypeError: request(...).then is not a function at exports.sendMessage.functions.firestore.document.onCreate (/srv/lib/index.js:25:12) at cloudFunction (/srv/node_modules/firebase-functions/lib/cloud-functions.js:127:23) at /worker/worker.js:825:24 at at process._tickDomainCallback (internal/process/next_tick.js:229:7)


回答1:


request supports callback interfaces natively but does not return a promise, which is what you must do within a Cloud Function.

This is explained in the official Firebase video series here: https://firebase.google.com/docs/functions/video-series/. In particular watch the three videos titled "Learn JavaScript Promises" (Parts 2 & 3 especially focus on background triggered Cloud Functions, but it really worth watching Part 1 before).

You could use request-promise (https://github.com/request/request-promise) and the rp() method which "returns a regular Promises/A+ compliant promise". You would then adapt your code as follows:

import * as functions from 'firebase-functions';

const admin = require('firebase-admin');

const rp = require('request-promise');


exports.sendMessage = functions.firestore.document('comms/{comms}').onCreate((snap, context) => {

    const newValue = snap.data();

    if (newValue) {

        const msg = newValue.msg;


        var options = {
            method: 'POST',
            uri: '....',
            body: msg,
            json: true // Automatically stringifies the body to JSON
        };

        return rp(options)
        .then(parsedBody => {
            // POST succeeded...
            console.log('SUCCESS! Posted', msg);
            return null;
        })
        .catch(err => {
            // POST failed...
            console.log(err);
            return null;
        });

    } else {
        return null;
    }

});



回答2:


request module doesn't return a Promise instead try using a callback function for response.

    return request({
  uri: "url",
  method: 'POST',
  body: msg,
  json: true,
  resolveWithFullResponse: true
}, function (error, response, body) {
})



回答3:


As in the documentation already mention you need to pass the callback to your request

var request = require('request');
request('http://www.google.com', function (error, response, body) {
  console.log('error:', error); // Print the error if one occurred
  console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
  console.log('body:', body); // Print the HTML for the Google homepage.
});

If you want to chain your request you can use pipe

request
  .get('url/img.png')
  .on('response', function(response) {
    console.log(response.statusCode) // 200
    console.log(response.headers['content-type']) // 'image/png'
  })
  .pipe(request.put('url'))

If you want to use promise you can use request-promise

var rp = require('request-promise');

rp('http://www.google.com')
    .then(function (htmlString) {
        // Process html...
    })
    .catch(function (err) {
        // Crawling failed...
    });



回答4:


The request module work on callbacks only, If you want to make Promisify you need to do like this

const request = require('request');

const webService = {};

webService.callApi = (url, bodyObj, method) => {
  return new Promise((resolve, reject) => {
    const options = {
      method: method || 'POST',
      url: url,
      headers: {
        'Content-Type': 'application/json',
      },
      body: bodyObj,
      json: true,
    };
    // Error Handler
    const errorMessge = { code: 500, error: 'INTERNAL_SERVER_ERROR' };

    request(options, (error, response, resBody) => {
      if (error) {
        return reject(errorMessge);
      } else if (response.statusCode !== 200) {
        return reject(errorMessge);
      }
      return resolve(resBody);
    });
  });
};

module.exports = webService;


来源:https://stackoverflow.com/questions/57594385/request-then-is-not-a-function-error-when-making-a-post-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!