如何处理Node.js中的callback?

假设我有3个文件。

index.js像这样调用后端

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

routes.js像这样处理路由

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

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 } 

何时/何时应该调用传递给getItems()来处理index.js中的成功/失败的callback?

因为你的request.post()操作是asynchronous的,所以你必须使用一些方法来跟踪他们什么时候完成,然后你可以调用你的callback函数。 有多种方法可以做到这一点。 我将概述几个:

手动logging请求操作的次数

 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(); } }); }); }); } 

手动执行此操作的主要问题是,在实际弄清楚如何处理错误时,在嵌套的asynchronous操作中传播错误是很困难的。 这在这里显示的其他方法中更容易。

使用承诺

 // 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 }) 

在你的服务器端代码中发出一个API请求似乎很奇怪,除非这是一些与API交互的中间层代码,但是你正在与一个数据库交互,所以我仍然感到困惑为什么你不能只是做一个数据库插入,或者有一个批量插入API调用?

无论如何,如果你必须按照你所要求的方式来做,我过去用recursion的方法来完成结果数组…我真的不知道这是一个好方法,所以我我想听听任何反馈。 像这样的东西:

 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); });