2015-10-20 59 views
1

假设我有3个文件。如何处理Node.js中的回调?

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中的成功/失败?

回答

2

因为你request.post()操作是异步,您必须使用跟踪时,他们都做的一些方法,然后你可以调用你的回调。有多种方式可以做到这一点。我将概述几点:

手动保持请求操作的计数的轨道

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

与手动这样做的主要问题是,传播嵌套异步操作的错误是很难当你真正弄清楚你将如何处理错误。这在这里显示的其他方法中更容易。

使用承诺

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

@JackJohnson - 为你做了这项工作? – jfriend00

+0

我还没有试过,明天我会试试看第一件事。谢谢。 –

+0

@ jfriend00,我很想知道'诺言'。map'排成一行** //错误在这里** getItems'的一部分...让我们假设你有20个项目用于'postAsync',其中15个成功,5个失败......将15个结果放在'results'中为了成功和5在错误中的错误?我对承诺有什么高层次的理解,但我还没有看到一个承诺数组的例子。 – incutonez

1

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

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

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

谢谢,只是需要在服务器端的API请求,以更新另一台服务器上的项目。尽管有点复杂,但看起来这是一个不错的选择。如果没有其他更简单的解决方案,我可能只是去解决这个问题。我的另一个想法是在函数之后使用lodash,并在那里调用回调函数。 –

+0

啊,好吧,那正是我所想的。你不能进行批量API调用吗?如果你已经抽象出了你的单个POST的逻辑,那么制作批量插入方法会非常容易。我同意这有点复杂,起初很混乱,但似乎为我完成了这项工作。 – incutonez

+0

你能解释批量API调用的含义吗? –