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
,因为局部范围是可变的。是的,我修复了它,我缺少了一些括号,这就是为什么我这么说?这并不意味着它已准备好复制和粘贴;)但是现在应该可以了谢谢你。你知道为什么我会在代码中出现这个错误吗