UnhandledPromiseRejectionWarning,Express.js和Node.js

时间:2018-07-23 18:12:44

标签: html node.js express server node-modules

我对 Node.js Express.js 完全陌生,并且一直在尝试通过一些示例将Shippo API集成到我的电子商务Web应用程序中但是我遇到了一些错误,尽管多次检查我的代码也无法解决。

我收到 UnhandledPromiseRejectionWarning 错误,从我在线阅读的内容来看,这意味着我的代码中某处有一个 .then()部分,但没有包含“捕获”或“要做的事情”是请求返回错误。任何帮助将不胜感激。

这是我的代码:

var express = require('express')
var app = express()
var http = require('http');
var Raven = require('raven');
var shippo = require('shippo')('ACCESS_TOKEN');
var engines = require('consolidate');
const bodyParser = require('body-parser');
const path = require('path');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.engine('html', engines.mustache);
app.set('view engine', 'html');
//app.use(express.static(path.join(_dirname,'/')));


app.get('/', function (req, res) {
  res.render('Index.html');
})
app.post('/', function (req, res) {

  var addressFrom  = {
      "object_purpose":"PURCHASE",
      "name": "SENDER_NAME",
      "company":"Shippo",
      "street1":"215 Clayton St.",
      "city":"San Francisco",
      "state":"CA",
      "zip":"94117",
      "country":"US", //iso2 country code
      "phone":"+1 555 341 9393",
      "email":"SENDER_EMAIL",
  };

  // example address_to object dict
  var addressTo = {
      "object_purpose":"PURCHASE",
      "name": req.body.fnames + ' ' + req.body.lnames,
      "company": req.body.company,
      "street1":req.body.street,
      "city":req.body.city,
      "state":req.body.state,
      "zip":req.body.zipcode,
      "country": req.body.country, //iso2 country code
      "phone":"+1 555 341 9393",
      "email":"support@goshippo.com",
  };

  // parcel object dict
  var parcelOne = {
      "length":"5",
      "width":"5",
      "height":"5",
      "distance_unit":"in",
      "weight":"2",
      "mass_unit":"lb"
  };


  var shipment = {
      "object_purpose": "PURCHASE",
      "address_from": addressFrom,
      "address_to": addressTo,
      "parcels": [parcelOne],
      "submission_type": "DROPOFF"
  };

  shippo.transaction.create({
      "shipment": shipment,
      "servicelevel_token": "ups_standard",
      "carrier_account": 'CARRIER_TOKEN',
      "label_file_type": "PDF"
  })
  .then(function(transaction) {
      shippo.transaction.list({
        "rate": transaction.rate
      })
      .then(function(mpsTransactions) {
          mpsTransactions.results.forEach(function(mpsTransaction){
              if(mpsTransaction.object_status == "SUCCESS") {
                  console.log("Label URL: %s", mpsTransaction.label_url);
                  console.log("Tracking Number: %s", mpsTransaction.tracking_number);
                  console.log("E-Mail: %s", mpsTransaction.object_owner);
                  console.log(mpsTransaction.object_status);
                  res.status(200).send("Label can be found under: " + mpsTransaction.label_url);
              } else {
                  // hanlde error transactions
                  console.log("Message: %s", mpsTransactions.messages);
              }
          });
      })
  }, function(err) {
      // Deal with an error
      console.log("There was an error creating transaction : %s", err.detail);
      res.send("something happened :O")
  });
})
app.post('/successp', function (req, res) {

  var token = req.body.stripeToken; // Using Express
  // Charge the user's card:
var charge = stripe.charges.create({
  amount: 1000,
  currency: "eur",
  description: "Example charge",
  source: token,
}, function(err, charge) {
  // asynchronously called
});
 res.send('Thanks!')
})
app.post('/successp', function (req, res) {

  var token = req.body.stripeToken; // Using Express
  // Charge the user's card:
var charge = stripe.charges.create({
  amount: 1000,
  currency: "eur",
  description: "Example charge",
  source: token,
}, function(err, charge) {
  // asynchronously called
});
 res.send('Thanks!')
})

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})

这是我得到的错误:

  

示例应用程序在端口3000上监听!   (节点:2378)UnhandledPromiseRejectionWarning   (节点:2378)UnhandledPromiseRejectionWarning:未处理的承诺拒绝。引发此错误的原因可能是抛出了一个没有catch块的异步函数,或者是拒绝了一个.catch()无法处理的承诺。 (拒绝ID:1)   (节点:2378)[DEP0018] DeprecationWarning:已弃用未处理的承诺拒绝。将来,未处理的承诺拒绝将以非零退出代码终止Node.js进程。

我也不完全确定某些代码行的用途(再次,我对表达和使用node.js非常陌生)。什么是引擎和胡须?另外,我看到此示例代码使用了 APP.POST('/ succesp',function(req,res)...)'/ succesp'到底是什么? >?我需要创建另一个HTML文件吗?另外,开头的“ app.use(express.statc([ath.join(_dirnam,'/'))); ”是什么?

2 个答案:

答案 0 :(得分:1)

您需要谨慎使用格式then(FN, errorFn),因为如果then内部出现错误,errorFn将无法捕获该错误。最好使用then(fn).catch(errorFn)。这样,上面任何then中的所有错误都可以过滤到最后一个catch进行处理。

例如,第一个调用正确捕获了错误,而第二个则没有:

function fn() {
  return Promise.resolve("good")
}

fn()
  .then(r => {
    throw ("whoops")
  })
  .catch(err => console.log(err)) //<-- catch works here

fn()
  .then(r => {
      throw ("whoops")
    },
    err => console.log(err) // this can't catch the error above; it will only catch rejections on fn()
  )

该代码段中未显示它,但是如果您查看控制台,则会看到未处理的拒绝错误。

在您的代码中,您可以通过从shippo.transaction.list返回承诺来拉平承诺链。然后,您可以在末尾添加一个catch以处理错误。

shippo.transaction.create({
    "shipment": shipment,
    "servicelevel_token": "ups_standard",
    "carrier_account": 'CARRIER_TOKEN',
    "label_file_type": "PDF"
})
.then(function(transaction) {
    return shippo.transaction.list({  // return this promise
    "rate": transaction.rate
})
.then(function(mpsTransactions) {     // so this can flatten out
    mpsTransactions.results.forEach(function(mpsTransaction){
        if(mpsTransaction.object_status == "SUCCESS") {
            console.log("Label URL: %s", mpsTransaction.label_url);
            console.log("Tracking Number: %s", mpsTransaction.tracking_number);
            console.log("E-Mail: %s", mpsTransaction.object_owner);
            console.log(mpsTransaction.object_status);
            res.status(200).send("Label can be found under: " + mpsTransaction.label_url);
        } else {
            // hanlde error transactions
            console.log("Message: %s", mpsTransactions.messages);
        }
    });
})
.catch(function(err) {   // catch errors
    // Deal with an error
    console.log("There was an error creating transaction : %s", err.detail);
    res.send("something happened :O")
});
})

由于很难在没有所有内容的情况下在本地运行,因此我对错误的来源并不满意,但是看起来您正在循环内发送res.status(200).send(),如果出现这种情况,可能会导致错误它被调用了两次。

答案 1 :(得分:1)

如果没有阅读完整的代码,则不应在使用Promises时尝试使用回调函数捕获错误。您可以使用 .catch

来捕获Promises中的错误。

您还应该返回第一个承诺,以便将其传递给下一个 .then 函数(如果您打算将shippo.transaction.list作为mpsTransactions返回)

类似这样的东西:

 shippo.transaction.create({
 "shipment": shipment,
 "servicelevel_token": "ups_standard",
 "carrier_account": 'CARRIER_TOKEN',
 "label_file_type": "PDF"
})
  .then(function(transaction) {
      return shippo.transaction.list({
        "rate": transaction.rate
      })
   })
  .then(function(mpsTransactions) {
    mpsTransactions.results.forEach(function(mpsTransaction){
        if(mpsTransaction.object_status == "SUCCESS") {
            console.log("Label URL: %s", mpsTransaction.label_url);
            console.log("Tracking Number: %s", mpsTransaction.tracking_number);
            console.log("E-Mail: %s", mpsTransaction.object_owner);
            console.log(mpsTransaction.object_status);
            res.status(200).send("Label can be found under: " + mpsTransaction.label_url);
        } else {
            // hanlde error transactions
            console.log("Message: %s", mpsTransactions.messages);
        }
    });
   })
  .catch(function (error) {
    // Deal with an error
    console.log("There was an error creating transaction : %s", err.detail);
    res.send("something happened :O")
  });