同步任务与异步任务

Synchronous tasks with asynchronous task

我正在将一个验证组件放在一个应用程序上,它接受一个任务名称(这将是一个字段名称)和一个值作为它的参数。对于每个找到的 form 字段,都会启动一个任务。

如果验证失败,则 return 出现错误,否则输入没问题,将启动下一个现场任务,直到处理完所有字段。

在下面的示例中,task_1 按预期工作。但是,在可能需要 HTTP 请求(由 setTimeout 模拟)的情况下,task_2 不会 return 所需的结果。

我确信这与异步性有关,也许有更好的方法来实现这种机制。这实际上将在 NodeJS 后端实现,其中 async 库可用,我会接受使用异步的解决方案。

请参阅此 Fiddle for the below example. Or this Fiddle 了解异步实现。

/**
 * Selecting task_1 below, will have the desired results,
 * however if you run task_2 the final task will not work?
 * A setTimeout() has been used to simulate a HTTP request etc..
 */

// output element
var $output = $$('output')

// configuration object, each task has an 
// array of functions which must accept a
// value which would be validated
var jobs = {
  task_1: [
    function(val, cb) {
      cb(null, val)
    },
    function(val, cb) {
      cb('Error', null)
    }
  ],
  task_2: [
    function(val, cb) {
      cb(null, val)
    },
    function(val, cb) {
      setTimeout(function() {
        cb('An ajax request has an error', null)
      }, 2000)
    }
  ]
}

// run a task and pass a value
taskRunner('task_2', 'Karl')

// taskRunner
function taskRunner(job, val) {
  var tasks = jobs[job]
  var errors = []

  if (tasks) {
    // run the found tasks
    for (i = 0; i < jobs[job].length; i++) {
      tasks[i](val, function(err, result) {
        if (err) {
          errors.push(err)
        }
      })
    }

    // generate the html output
    var html = errors.length > 0 ? [
      '<strong class="text-danger">',
      'Failure</strong>',
      '<pre>',
      errors,
      '</pre>'
    ].join('') : [
      '<strong class="text-success">',
      'Success</strong>',
      '<pre>All validations passed</pre>'
    ].join('')
    $output.html(html).fadeIn()
  } else {
    // return an error message if no tasks have been found
    $output.html('<span class="text-danger">There are no tasks for ' + job + '.</span>').fadeIn()
  }
}

// select elements by data attribute
function $$(val) {
  return $('[data-' + val + ']')
}
/* default */
html,
body {
  margin: 0;
  padding: 0;
  font-family: "Lucida Console", Monaco, monospace !important;
  background: whitesmoke;
  color: #333;
}


/* output container */
.output {
  max-width: 75%;
  margin: 5% auto;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 3px;
  background: white;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}


/* formatted output */
pre {
  background: #FAFAFA;
  padding: 15px;
  margin-bottom: 0;
}


/* type styles */
.text-muted {
  opacity: .5
}

.text-danger {
  color: #D00
}

.text-success {
  color: #0D0
}


/* hide if empty */
.js-hide {
  display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="output js-hide" data-output></div>

the best way to complete your requirement using async .
var async = require('async');
var name = ["shekhar", 'vishal', "param", "abhishek", 'amit'];
    for (var i = 0; i < 5; i++) {
        var task_1 = name[i];//execute your first loop here
    }
    async.eachSeries(task_1, task_2, function (err) {
        if (err) {
            res.json({status: 0, msg: "OOPS! How is this possible?"});
        }
        res.json("Series Processing Done");
    })
    function task_2(item, callback) {
//execute your second loop here
        });

你应该在所有回调完成后生成 html 输出

为了这个目的,你可以使用 promise.all

但对于回调,您可以使用此代码

var doneCallback=0;
for (i = 0; i < jobs[job].length; i++) {
  tasks[i](val, function(err, result) {
    if (err) {
      errors.push(err)
    }
    doneCallback++;
    if(doneCallback==jobs[job].length)generateHtml();
  })
}

// generate the html output
function generateHtml(){
  var html = errors.length > 0 ? [
     '<strong class="text-danger">',
     'Failure</strong>',
     '<pre>',
     errors,
     '</pre>'
   ].join('') : [
     '<strong class="text-success">',
     'Success</strong>',
     '<pre>All validations passed</pre>'
   ].join('')
   $output.html(html).fadeIn();
}

/**
 * Selecting task_1 below, will have the desired results,
 * however if you run task_2 the final task will not work?
 * A setTimeout() has been used to simulate a HTTP request etc..
 */

// output element
var $output = $$('output')

// configuration object, each task has an 
// array of functions which must accept a
// value which would be validated
var jobs = {
  task_1: [
    function(val, cb) {
      cb(null, val)
    },
    function(val, cb) {
      cb('Error', null)
    }
  ],
  task_2: [
    function(val, cb) {
      cb(null, val)
    },
    function(val, cb) {
      setTimeout(function() {
        cb('An ajax request has an error', null)
      }, 2000)
    }
  ]
}

// run a task and pass a value
taskRunner('task_2', 'Karl')

// taskRunner
function taskRunner(job, val) {
  var tasks = jobs[job]
  var errors = []

  if (tasks) {
    // run the found tasks
    var doneCallback=0;
    for (i = 0; i < jobs[job].length; i++) {
       tasks[i](val, function(err, result) {
          if (err) {
            errors.push(err)
          }
          doneCallback++;
          if(doneCallback==jobs[job].length)generateHtml();
       })
    }

    // generate the html output
    function generateHtml(){
       var html = errors.length > 0 ? [
         '<strong class="text-danger">',
         'Failure</strong>',
         '<pre>',
          errors,
         '</pre>'
        ].join('') : [
          '<strong class="text-success">',
          'Success</strong>',
          '<pre>All validations passed</pre>'
        ].join('')
       $output.html(html).fadeIn();
     }
  } else {
    // return an error message if no tasks have been found
    $output.html('<span class="text-danger">There are no tasks for ' + job + '.</span>').fadeIn()
  }
}

// select elements by data attribute
function $$(val) {
  return $('[data-' + val + ']')
}
/* default */
html,
body {
  margin: 0;
  padding: 0;
  font-family: "Lucida Console", Monaco, monospace !important;
  background: whitesmoke;
  color: #333;
}


/* output container */
.output {
  max-width: 75%;
  margin: 5% auto;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 3px;
  background: white;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}


/* formatted output */
pre {
  background: #FAFAFA;
  padding: 15px;
  margin-bottom: 0;
}


/* type styles */
.text-muted {
  opacity: .5
}

.text-danger {
  color: #D00
}

.text-success {
  color: #0D0
}


/* hide if empty */
.js-hide {
  display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="output js-hide" data-output></div>