Javascript Node.js表单提交异步错误反馈?

Javascript Node.js表单提交异步错误反馈?,javascript,node.js,forms,asynchronous,Javascript,Node.js,Forms,Asynchronous,异步功能使Node.js非常强大和快速。但假设您正在使用Express之类的东西制作一个web应用程序,并且您有一个表单供访问者填写。提交表单时,它会通过电子邮件将数据发送给某人,并将数据保存到数据库中 现在有了Node,我的第一反应是做如下事情(伪代码): 因此,您有两个异步函数,它们同时发生,发送电子邮件并将数据放入数据库。当这些事情发生在服务器上时,访问者被重定向到某种“感谢您提交表单”页面。这充分利用了Node.js的异步功能 但是,如果这两个异步函数中的一个出现错误,您该怎么办?可能是

异步功能使Node.js非常强大和快速。但假设您正在使用Express之类的东西制作一个web应用程序,并且您有一个表单供访问者填写。提交表单时,它会通过电子邮件将数据发送给某人,并将数据保存到数据库中

现在有了Node,我的第一反应是做如下事情(伪代码):

因此,您有两个异步函数,它们同时发生,发送电子邮件并将数据放入数据库。当这些事情发生在服务器上时,访问者被重定向到某种“感谢您提交表单”页面。这充分利用了Node.js的异步功能

但是,如果这两个异步函数中的一个出现错误,您该怎么办?可能是电子邮件发送失败或数据库服务器脱机?既然访问者已经被重定向,您如何向他们提供错误反馈

您是否使用承诺或其他方式强制访问者等待两个异步函数完成,然后再向它们发送“谢谢”消息或“提交表单时出错”消息?如果您使用这种方法,那么首先您就有点失去了使用Node.js的异步优势,您实际上是在模拟PHP类型的响应


最好的方法是什么?

所有可能的答案都会有偏差,所以我解释我的方法,因为到目前为止,我看到的方法主要是使用适当的库(如或)来控制异步代码的执行。特别是Async.seq可以以优雅的方式帮助您。库中的示例:

// Requires lodash (or underscore), express3 and dresende's orm2.
// Part of an app, that fetches cats of the logged user.
// This example uses `seq` function to avoid overnesting and error
// handling clutter.
app.get('/cats', function(request, response) {
  var User = request.models.User;
  async.seq(
    _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
    function(user, fn) {
      user.getCats(fn);      // 'getCats' has signature (callback(err, data))
    }
  )(req.session.user_id, function (err, cats) {
    if (err) {
      console.error(err);
      response.json({ status: 'error', message: err.message });
    } else {
      response.json({ status: 'ok', message: 'Cats found', data: cats });
    }
  });
});
Promise.all([Promise.resolve('a'), 'b', Promise.resolve('c')])
  .then(function (res) {
    assert(res[0] === 'a')
    assert(res[1] === 'b')
    assert(res[2] === 'c')
  })
但你可能会发现这很简单&不够闪亮或不合适。然后你可以使用。在你的场景中,答应我,一切都会很好。库中的示例:

// Requires lodash (or underscore), express3 and dresende's orm2.
// Part of an app, that fetches cats of the logged user.
// This example uses `seq` function to avoid overnesting and error
// handling clutter.
app.get('/cats', function(request, response) {
  var User = request.models.User;
  async.seq(
    _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
    function(user, fn) {
      user.getCats(fn);      // 'getCats' has signature (callback(err, data))
    }
  )(req.session.user_id, function (err, cats) {
    if (err) {
      console.error(err);
      response.json({ status: 'error', message: err.message });
    } else {
      response.json({ status: 'ok', message: 'Cats found', data: cats });
    }
  });
});
Promise.all([Promise.resolve('a'), 'b', Promise.resolve('c')])
  .then(function (res) {
    assert(res[0] === 'a')
    assert(res[1] === 'b')
    assert(res[2] === 'c')
  })

所有可能的答案在某种程度上都会有偏差,所以我解释了我的答案,因为到目前为止,我看到的主要是使用适当的库(如或)来控制异步代码的执行。特别是Async.seq可以以优雅的方式帮助您。库中的示例:

// Requires lodash (or underscore), express3 and dresende's orm2.
// Part of an app, that fetches cats of the logged user.
// This example uses `seq` function to avoid overnesting and error
// handling clutter.
app.get('/cats', function(request, response) {
  var User = request.models.User;
  async.seq(
    _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
    function(user, fn) {
      user.getCats(fn);      // 'getCats' has signature (callback(err, data))
    }
  )(req.session.user_id, function (err, cats) {
    if (err) {
      console.error(err);
      response.json({ status: 'error', message: err.message });
    } else {
      response.json({ status: 'ok', message: 'Cats found', data: cats });
    }
  });
});
Promise.all([Promise.resolve('a'), 'b', Promise.resolve('c')])
  .then(function (res) {
    assert(res[0] === 'a')
    assert(res[1] === 'b')
    assert(res[2] === 'c')
  })
但你可能会发现这很简单&不够闪亮或不合适。然后你可以使用。在你的场景中,答应我,一切都会很好。库中的示例:

// Requires lodash (or underscore), express3 and dresende's orm2.
// Part of an app, that fetches cats of the logged user.
// This example uses `seq` function to avoid overnesting and error
// handling clutter.
app.get('/cats', function(request, response) {
  var User = request.models.User;
  async.seq(
    _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
    function(user, fn) {
      user.getCats(fn);      // 'getCats' has signature (callback(err, data))
    }
  )(req.session.user_id, function (err, cats) {
    if (err) {
      console.error(err);
      response.json({ status: 'error', message: err.message });
    } else {
      response.json({ status: 'ok', message: 'Cats found', data: cats });
    }
  });
});
Promise.all([Promise.resolve('a'), 'b', Promise.resolve('c')])
  .then(function (res) {
    assert(res[0] === 'a')
    assert(res[1] === 'b')
    assert(res[2] === 'c')
  })

我个人在任何地方都使用承诺。在您的情况下,我将只使用函数,当两个承诺都完成时,您可以发送响应。如果发生错误,那么您将处于捕获部分,在该部分中,您可以随心所欲地执行任何操作。在这种情况下,您如何“失去使用Node.js的异步优势”?非阻塞I/O并不意味着单个操作的处理速度更快。这只是意味着I/O操作不会阻塞主线程。我个人在任何地方都使用承诺。在您的情况下,我将只使用函数,当两个承诺都完成时,您可以发送响应。如果发生错误,那么您将处于捕获部分,在该部分中,您可以随心所欲地执行任何操作。在这种情况下,您如何“失去使用Node.js的异步优势”?非阻塞I/O并不意味着单个操作的处理速度更快。这只是意味着I/O操作不会阻塞主线程。