Javascript Can';t在循环中构建数组后发送头后设置头
我正在尝试构建一个对象数组并发送到客户端。接收错误:Javascript Can';t在循环中构建数组后发送头后设置头,javascript,node.js,Javascript,Node.js,我正在尝试构建一个对象数组并发送到客户端。接收错误: throw new Error('发送头后无法设置头'); ^ 错误:发送邮件后无法设置邮件头。 在ServerResponse.OutgoingMessage.setHeader(_http_outgoing.js:357:11) 在ServerResponse.header(D:\Dropbox(Personal)\coding\coinTracker5\node\u modules\expr ess\lib\response.js:7
throw new Error('发送头后无法设置头');
^
错误:发送邮件后无法设置邮件头。
在ServerResponse.OutgoingMessage.setHeader(_http_outgoing.js:357:11)
在ServerResponse.header(D:\Dropbox(Personal)\coding\coinTracker5\node\u modules\expr ess\lib\response.js:725:10)
在ServerResponse.send(D:\Dropbox(Personal)\coding\coinTracker5\node\u modules\expres s\lib\response.js:170:12)
在ServerResponse.json(D:\Dropbox(Personal)\coding\coinTracker5\node\u modules\expres s\lib\response.js:256:15)
在D:\Dropbox(个人)\coding\coinTracker5\routes\index.js:58:11
在D:\Dropbox(个人)\coding\coinTracker5\node\u modules\cryptox\lib\index.js:51:9
位于D:\Dropbox(个人)\coding\coinTracker5\node\u modules\cryptox\lib\bitfinex.js:93:13
在D:\Dropbox(个人)\coding\coinTracker5\node\u modules\cryptox\lib\bitfinex.js:72:13
应请求。\回调(D:\Dropbox(Personal)\coding\coinTracker5\node\u modules\bitfinex-api node\rest.js:95:16)
在Request.self.callback(D:\Dropbox(Personal)\coding\coinTracker5\node\u modules\requ est\Request.js:187:22)
您的res.json
在for循环中。循环将完成迭代并在获取速率之前调用res.json
。如果您希望获得所有费率,则可能需要等待所有getRate
调用完成后才能响应。我会用承诺来实现这一点
// if getRate returned a promise
var rates = cryptox.map(item => new Promise((resolve, reject) => {
item.getRate({pair:'XBT_USD'}, (err, rate) => {
if (err) return reject(err);
return resolve(rate);
})
})
Promise.all(rates)
.then(res.json);
我现在意识到仅仅说使用承诺并没有多大帮助。这是一个非承诺版本。这是放在一起的飞行,但应该工作
function mapAsync (fn, list, cb) {
var newList = [];
var i = 0;
function counter (err, value) {
console.log('count', value)
if (err) return cb(err);
newList.push(value);
if (i === list.length -1) return cb(newList);
i++;
callItem();
}
function callItem () {
return fn(list[i], counter)
}
return callItem();
}
function getRateFromItem (item, cb) {
return i.getRate({pair:'XBT_USD'}, cb);
}
mapAsync(getRateFromItem, cryptoxArray, (err, values) => {
// as long as there is no err you should have your array of values
})
您的res.json
位于for
循环中。循环将完成迭代并在获取速率之前调用res.json
。如果您希望获得所有费率,则可能需要等待所有getRate
调用完成后才能响应。我会用承诺来实现这一点
// if getRate returned a promise
var rates = cryptox.map(item => new Promise((resolve, reject) => {
item.getRate({pair:'XBT_USD'}, (err, rate) => {
if (err) return reject(err);
return resolve(rate);
})
})
Promise.all(rates)
.then(res.json);
我现在意识到仅仅说使用承诺并没有多大帮助。这是一个非承诺版本。这是放在一起的飞行,但应该工作
function mapAsync (fn, list, cb) {
var newList = [];
var i = 0;
function counter (err, value) {
console.log('count', value)
if (err) return cb(err);
newList.push(value);
if (i === list.length -1) return cb(newList);
i++;
callItem();
}
function callItem () {
return fn(list[i], counter)
}
return callItem();
}
function getRateFromItem (item, cb) {
return i.getRate({pair:'XBT_USD'}, cb);
}
mapAsync(getRateFromItem, cryptoxArray, (err, values) => {
// as long as there is no err you should have your array of values
})
当调用任何回调时,我已经等于length,不能使用这样的循环。我的建议是用一张期票,做一个促销。所有这些都是为了这个或是为了一辈子
伊夫
我个人最喜欢的就是这样的东西
import Promise from 'bluebird';
Promise.all(
cryptoxArray.map(
item => Promise.promisify(item. getRate)({pair: "XBT_USD"})
.then(rate => rate, error => null)
)
)
.then(rates => rates.filter(rate => rate !== null))
.then(res.json);
当调用任何回调时,我已经等于length,不能使用这样的循环。我的建议是用一张期票,做一个促销。所有这些都是为了这个或是为了一辈子
伊夫
我个人最喜欢的就是这样的东西
import Promise from 'bluebird';
Promise.all(
cryptoxArray.map(
item => Promise.promisify(item. getRate)({pair: "XBT_USD"})
.then(rate => rate, error => null)
)
)
.then(rates => rates.filter(rate => rate !== null))
.then(res.json);
只需使用async each在发送响应之前等待所有异步回调:
var rates = [];
async.each(cryptoxArray, function(e, callback) {
e.getRate({
pair: "XBT_USD"
}, function(err, rateResponse) {
if (!err){
rates.push(rateResponse);
}
callback();
});
},
function(err){
return res.json(rates);
});
只需使用async each在发送响应之前等待所有异步回调:
var rates = [];
async.each(cryptoxArray, function(e, callback) {
e.getRate({
pair: "XBT_USD"
}, function(err, rateResponse) {
if (!err){
rates.push(rateResponse);
}
callback();
});
},
function(err){
return res.json(rates);
});
我最近遇到了一个类似的问题,我正在寻找属于父属性的一组属性的所有数据,在尝试了一天不同的事情后,找到了具有以下片段的解决方案:
Model.find({field: req.params.id})
.then(response1 => {
let myexpected = response1.map(item => new Promise((resolve, reject) => {
Model2.find({field: item._id}, (err, resolveData) => {
if (err) return reject(err);
return resolve(resolveData);
})
}));
Promise.all(myexpected)
.then(expectedData => {
console.log(expectedData);
res.status(200).json({data: expectedData});
})
})
我希望这对您有所帮助,或者对另一个正在寻找类似解决方案的人有所帮助。我最近遇到了一个类似的问题,我正在寻找属于父属性的一组属性的所有数据,经过一天的尝试,找到了具有以下片段的解决方案:
Model.find({field: req.params.id})
.then(response1 => {
let myexpected = response1.map(item => new Promise((resolve, reject) => {
Model2.find({field: item._id}, (err, resolveData) => {
if (err) return reject(err);
return resolve(resolveData);
})
}));
Promise.all(myexpected)
.then(expectedData => {
console.log(expectedData);
res.status(200).json({data: expectedData});
})
})
我希望这对您有所帮助,或者对其他寻求类似解决方案的人有所帮助。您能帮助我了解在这种情况下如何使用承诺吗?我今天一直在阅读有关承诺的内容,对此我感到头晕目眩。getRate返回json,比如:{“timestamp”:“2016-10-16T15:00:07Z”,“error”:“data”:[{“pair”:“EUR_-USD”,“rate”:“1.09727328”}]}
@chuckieDub我认为评论不是学习承诺的地方。互联网上为他们提供了大量的资源。尝试一下,并把你遇到的任何问题都转发给我。你能帮我理解在这种特殊情况下如何使用承诺吗?我今天一直在阅读有关承诺的内容,对此我感到头晕目眩。getRate返回json,比如:{“timestamp”:“2016-10-16T15:00:07Z”,“error”:“data”:[{“pair”:“EUR_-USD”,“rate”:“1.09727328”}]}
@chuckieDub我认为评论不是学习承诺的地方。互联网上为他们提供了大量的资源。尝试一下,并将遇到的任何问题重新发布。谢谢。你知道为什么我会在代码中出现这个错误吗<代码>然后(res.json);^SyntaxError:missing)在参数列表之后
正如我在回答的开头所解释的,您依靠回调内部的循环计数器来确定何时发送数据。问题是,当第一次回调为execute时,所有回调的i==length-->true,因此每次在打开的连接上执行回调时,您都将调用res.json,因此会出现错误。第一次执行res.json时,将设置并发送响应头。你不能更改它们,这就是当你第二次使用res.json时它将尝试做的事情。我的意思是我尝试使用你的代码,但收到了错误。哪一个?承诺还是生命?如果是iife,请确保在iife内部将i
替换为index
,因为局部范围是可变的。是的,我修复了它,我缺少了一些括号,这就是为什么我这么说?这并不意味着它已准备好复制和粘贴;)但是现在应该可以了谢谢你。你知道为什么我会在代码中出现这个错误吗