简体   繁体   English

如何处理Node.js中的回调?

[英]How to handle callbacks in Node.js?

Let's say I have 3 files. 假设我有3个文件。

index.js makes a call to the backend like this index.js像这样调用后端

$.post('/test/', data, function(response) {
 //handle success here
})

routes.js handles the route like this routes.js像这样处理路由

app.post('/test/', function(req, res){
   item.getItems(function(response){
     res.json(response);
   });
 });

items.js is the model which accesses the database and makes a POST request for each item items.js是访问数据库并为每个项目发出POST请求的模型

function getItems(callback) {
  database.query('SELECT * from items', function(result){
    result.forEach(function(item){
        request.post('/api/', item, function(req, res) {
          //finished posting item
        });
    });   
  });
  //callback here doesnt wait for calls to finish
}

where/when should I call the callback passed to getItems() to handle a success/failure in index.js? 应该在何处/何时调用传递给getItems()的回调来处理index.js中的成功/失败?

Because your request.post() operations are async, you have to use some method of keeping track of when they are all done and then you can call your callback. 因为你的request.post()操作是异步的,你必须使用一些方法来跟踪它们何时完成,然后你可以调用你的回调。 There are multiple ways of doing that. 有多种方法可以做到这一点。 I'll outline a few: 我将概述几个:

Manually Keeping Track of Count of Request Operations 手动跟踪请求操作的数量

function getItems(callback) {
  database.query('SELECT * from items', function(result){
    var remaining = result.length;
    result.forEach(function(item){
        request.post('/api/', item, function(err, res) {
          --remaining;
          //finished posting item
          if (remaining === 0) {
              callback();
          }
        });
    });   
  });
}

The main problem with doing this manually is that propagating error in nested async operations is difficult when you get to actually figuring out how you're going to handle errors. 手动执行此操作的主要问题是,当您真正弄清楚如何处理错误时,嵌套异步操作中的传播错误很困难。 This is much easier in the other methods shown here. 这在此处显示的其他方法中更容易。

Using Promises 使用承诺

// load Bluebird promise library
var Promise = require('bluebird');

// promisify async operations
Promise.promisifyAll(request);

function queryAsync(query) {
    return new Promise(function(resolve, reject) {
        // this needs proper error handling from the database query
        database.query('SELECT * from items', function(result){
            resolve(result);
        });
    });
}

function getItems(callback) {
    return queryAsync('SELECT * from items').then(function(result) {
        return Promise.map(result, function(item) {
            return request.postAsync('/api/', item);
        });
    });
}

getItems.then(function(results) {
    // success here
}, function(err) {
    // error here
})

It seems strange that you're making an API request in your server-side code, unless this is some sort of middle tier code that interacts with the API... but you're interacting with a database, so I'm still confused on why you can't just do a database insert, or have a bulk insert API call? 您在服务器端代码中发出API请求似乎很奇怪,除非这是与API交互的某种中间层代码......但是您正在与数据库进行交互,所以我仍然感到困惑为什么你不能只是进行数据库插入,或者有批量插入API调用?

Anyway, if you must do it the way you're asking, I've done this in the past with a recursive method that trims down the result array... I really don't know if this is a good approach, so I'd like to hear any feedback. 无论如何,如果你必须按照你要求的方式做到这一点,我过去已经用一个递归方法完成了这个,它减少了结果数组...我真的不知道这是不是一个好方法,所以我我想听到任何反馈。 Something like this: 像这样的东西:

function recursiveResult(result, successfulResults, callback) {
  var item = result.shift();
  // if item is undefined, then we've hit the end of the array, so we'll call the original callback
  if (item !== undefined) {
    console.log(item, result);
    // do the POST in here, and in its callback, call recursiveResult(result, successfulResults, callback);
    successfulResults.push(item);
    return recursiveResult(result, successfulResults, callback);
  }
  // make sure callback is defined, otherwise, server will crash
  else if (callback) {
    return callback(successfulResults);
  }
  else {
    // log error... callback undefined
  }
}

function getItems(callback) {
  var successfulResults = [];
  var result = [1, 2, 3, 4];
  recursiveResult(result, successfulResults, callback);
}

console.log('starting');
getItems(function(finalResult) {
  console.log('done', finalResult);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM