Node.js:如何处理循环中的回调?
我正在使用Node.js和Box SDK。我的(失败!)代码如下所示:Node.js:如何处理循环中的回调?,node.js,for-loop,asynchronous,Node.js,For Loop,Asynchronous,我正在使用Node.js和Box SDK。我的(失败!)代码如下所示: var connection = box.getConnection(req.user.login); connection.ready(function () { connection.getFolderItems(0, null, function (err, result) { if (err) { opts.body = err; } else { opts.body =
var connection = box.getConnection(req.user.login);
connection.ready(function () {
connection.getFolderItems(0, null, function (err, result) {
if (err) {
opts.body = err;
} else {
opts.body = result;
var a = [];
for (var i=0; i < result.entries.length; i++) {
connection.getFileInfo(result.entries[i].id, function (err, fileInfo) {
if (err) {
opts.body = err;
} else {
a.push(fileInfo);
}
});}
}
var Promise = require('bluebird');
var connection = Promise.promisifyAll(box.getConnection(req.user.login));
connection.ready(function() {
connection.getFolderItemsAsync(0, null).then(function(result) {
return Promise.map(result.entries, function(item) {
return connection.getFileInfoAsync(item.id).catch(function(err){
// post the results as null and continue with the other results
return null;
});
})
}).then(function(results) {
// array of results here (some might be null if they had an error)
}, function(err) {
// error here
});
});
我的问题是connection.getFolderItems()
和connection.getFileInfo()
是异步的-在返回所有结果之前,“for”循环退出
问:在Node.js中,1)获取第一个异步调用的结果,2)遍历列表,进行更多异步调用,以及3)在“完成”所有操作后处理结果的最佳方法是什么
问:你在这里是个不错的选择吗
问:这是一种选择吗
问:Node.js中是否有针对此类场景的“标准习惯用法”
问:在Node.js中,获得第一个结果的最佳方法是什么
异步调用,2)遍历列表,进行更多异步调用,以及
3) 当一切都“完成”时处理结果
有多种方法。手工编码,承诺,异步库。“最好的”是在旁观者的眼里,所以我们在这里不是真的要说。我所有的异步编码都使用承诺。它们已经在ES6中正式标准化,并且有很好的、健壮的实现(我喜欢Bluebird,因为它在简化复杂异步任务的标准之外还有一些额外的特性,还有它的promisifyAll()
功能,为使用异步回调调用约定的任何标准异步操作提供承诺接口)
我建议不要手工编写复杂的异步操作,因为健壮的错误处理非常困难,异常可以在异步回调中被默默地吃掉,从而导致错误处理丢失和调试困难。异步库可能是最好的非承诺方式,因为它围绕异步回调提供了一些基础结构和同步功能
我个人更喜欢承诺。我认为随着时间的推移,我们将看到更多的异步API在返回承诺方面实现标准化,因此我认为这是一种更好的前瞻性学习和编程方法
问:承诺在这里是一个好的选择吗
是的,Promission允许您运行一系列异步操作,然后使用类似于Promise.all()
的方法来知道它们何时完成。它还将为您收集所有异步操作的所有结果
问:done()/next()是选项吗
我不太清楚您在这里问的是什么,但是您可以手动编写异步操作代码,使其并行运行并知道何时完成,或者按顺序运行并知道何时完成。承诺可以为您完成更多这方面的工作,但您可以在没有承诺的情况下手动完成
问:Node.js中是否有针对此类场景的“标准习惯用法”
如果使用承诺,将有一个共同的方式来做到这一点。如果不使用承诺,可能就没有“标准习惯用法”,因为有许多不同的方法可以自己编写
承诺实施
下面是一个使用node.js中的Bluebird Promise库的示例:
var Promise = require('bluebird');
var connection = Promise.promisifyAll(box.getConnection(req.user.login));
connection.ready(function() {
connection.getFolderItemsAsync(0, null).then(function(result) {
return Promise.map(result.entries, function(item) {
return connection.getFileInfoAsync(item.id);
})
}).then(function(results) {
// array of results here
}, function(err) {
// error here
});
});
下面是它的工作原理:
getFolderItemsAsync()
,它的承诺将通过结果来解决
connection.getFileInfoAsync()
实现的null
结果,则可以使用以下方法:
var connection = box.getConnection(req.user.login);
connection.ready(function () {
connection.getFolderItems(0, null, function (err, result) {
if (err) {
opts.body = err;
} else {
opts.body = result;
var a = [];
for (var i=0; i < result.entries.length; i++) {
connection.getFileInfo(result.entries[i].id, function (err, fileInfo) {
if (err) {
opts.body = err;
} else {
a.push(fileInfo);
}
});}
}
var Promise = require('bluebird');
var connection = Promise.promisifyAll(box.getConnection(req.user.login));
connection.ready(function() {
connection.getFolderItemsAsync(0, null).then(function(result) {
return Promise.map(result.entries, function(item) {
return connection.getFileInfoAsync(item.id).catch(function(err){
// post the results as null and continue with the other results
return null;
});
})
}).then(function(results) {
// array of results here (some might be null if they had an error)
}, function(err) {
// error here
});
});
手动编码版本 这是一个手动编码的版本。这个问题的关键是通过比较
if(results.length==result.entries.length)
来检测异步循环何时完成。注意:这有不完整的错误处理,这是手工编码和不使用异步框架(如Promissions)的困难之一
var connection = box.getConnection(req.user.login);
connection.ready(function () {
connection.getFolderItems(0, null, function (err, result) {
if (err) {
// do error handling here
opts.body = err;
} else {
var results = [];
for (var i = 0; i < result.entries.length; i++) {
connection.getFileInfo(result.entries[i].id, function (err, fileInfo) {
if (err) {
// do error handling here
opts.body = err;
results.push(null);
} else {
results.push(fileInfo);
}
// if done with all requests
if (results.length === result.entries.length) {
// done with everything, results are in results
// process final results here
}
});
}
}
});
});
var connection=box.getConnection(请求用户登录);
connection.ready(函数(){
getFolderItems(0,null,函数(err,result){
如果(错误){
//请在此处执行错误处理
opts.body=err;
}否则{
var结果=[];
对于(var i=0;i
问:在Node.js中,获得第一个结果的最佳方法是什么
异步调用,2)遍历列表,进行更多异步调用,以及
3) 当一切都“完成”时处理结果
您可以使用库或promisify函数调用并使用Promise。两者都很容易使用
问:承诺在这里是一个好的选择吗
对。但它要求你在使用之前先提出你的方法
Q:Is done()/next