【问题标题】:Ensure tasks are completing in order确保任务按顺序完成
【发布时间】:2017-05-30 12:09:42
【问题描述】:

我们正在使用 mailgun,我们的一些用户被列入黑名单。一次删除多个用户可能很乏味,所以我想通过 API 做同样的事情。我还想保存一些有关用户电子邮件被退回的原因的信息,以便我可以将其转发给他们。我这样做是这样的:

fs.readFile('emails.txt', 'utf8', function(err, data) { 
  if (err) throw err;
  var emails = data.split(',');
  async.eachSeries(emails, function(email, cb){
    options.url = 'https://api.mailgun.net/v3/XXXXX.com/bounces/'+email

    request.get(options, function(err, res, body){
      body = JSON.parse(body);
      error_code = body.error;
      bounced_at = body.created_at;

      var str = "\n Error code: "+body.error+" for email: "+email+" was bounced at: "+body.created_at
      fs.appendFile("output.txt", str, function(err){
        if(err) console.log(err)
        console.log("Details were saved to output.txt")
      })
    });
    request.del(options, function(err, res, body){
      if(err){
        cb(err);
      } else {
        console.log('Email: '+email+' has been unsuppressed');
      }
    })
    cb(null);
  }, function(err){
    if(err){
      console.log(err);
    } else {
      console.log('All bounced emails removed')
    }
  });
});

下面是一个有 5 个用户的测试。

输入:

test1@ah.com,test2@ah.com,test3@ah.com,test4@ah.com,test5@ah.com

输出:

Error code: 4.4.4 for email: test4@ah.com was bounced at: Tue, 30 May 2017 11:40:17 UTC Error code: 3.3.3 for email: test3@ah.com was bounced at: Tue, 30 May 2017 11:40:05 UTC Error code: 2.2.2 for email: test2@ah.com was bounced at: Tue, 30 May 2017 11:39:57 UTC Error code: 1.1.1 for email: test1@ah.com was bounced at: Tue, 30 May 2017 11:39:45 UTC Error code: 5.5.5 for email: test5@ah.com was bounced at: Tue, 30 May 2017 11:40:27 UTC

我们可以看到这些没有按顺序完成,这很好。当然这在异步文档here 中已经足够了。

请注意,由于此函数将 iteratee 并行应用于每个项目,因此无法保证 iteratee 函数将按顺序完成。

但是,当我用十封电子邮件进行测试时:

test1@ah.com,test2@ah.com,test3@ah.com,test4@ah.com,test5@ah.com,test6@ah.com,test7@ah.com,test7@ah.com,test8@ah.com,test9@ah.com,test10@ah.com

这是输出:

Error code: 2.2.2 for email: test2@ah.com was bounced at: Tue, 30 May 2017 11:43:57 UTC Error code: undefined for email: test10@ah.com was bounced at: undefined Error code: 1.1.1 for email: test1@ah.com was bounced at: Tue, 30 May 2017 11:43:50 UTC Error code: 8.8.8 for email: test8@ah.com was bounced at: Tue, 30 May 2017 11:44:43 UTC Error code: 3.3.3 for email: test3@ah.com was bounced at: Tue, 30 May 2017 11:44:05 UTC Error code: 6.6.6 for email: test6@ah.com was bounced at: Tue, 30 May 2017 11:44:28 UTC Error code: 5.5.5 for email: test5@ah.com was bounced at: Tue, 30 May 2017 11:44:21 UTC Error code: 4.4.4 for email: test4@ah.com was bounced at: Tue, 30 May 2017 11:44:13 UTC Error code: undefined for email: test7@ah.com was bounced at: undefined Error code: 9.9.9 for email: test9@ah.com was bounced at: Tue, 30 May 2017 11:44:55 UTC

似乎在某些情况下,我的request.get() 是在request.del() 之后执行的 -> 这导致输出日志在某些地方具有Undefined。如何确保始终先执行request.get()

【问题讨论】:

  • 摆脱回调,使用承诺。
  • @loan 你能证明这一点,我很乐意接受答案。

标签: javascript node.js asynchronous


【解决方案1】:

使用回调,您可以通过在第一个回调中调用第二个异步函数来指定顺序,其中 first 和 second 是您希望它们执行的顺序。

first("foo", function() {
  // inside callback of first function
  second("bar", function() {
    // second callback. 
    // At this point both functions have terminated in order
...

虽然这对于 2 或 3 个嵌套回调是可以的,但您很容易陷入 回调地狱

处理异步函数的另一种方法是使用Promises

当函数返回 Promise 时,您可以访问 .then() 方法,该方法将 Promise 解析时要调用的函数作为参数(第一个异步函数完成异步操作)

它看起来像这样:

something_async_way("foo", "bla").then(function() { // do something });

更多关于 Promises 的信息here

【讨论】:

  • 将在接受答案之前尝试使用承诺实现
  • 好的。我假设您在 node.js 文件中使用 request 模块。在这种情况下,由于它不支持开箱即用的 Promises,您需要使用 this
  • 是的,我正在使用request 模块来访问 api。我会调查request-promise,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-24
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 1970-01-01
相关资源
最近更新 更多