Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将node.js请求包装到promise和piping中_Javascript_Node.js_Promise_Request - Fatal编程技术网

Javascript 将node.js请求包装到promise和piping中

Javascript 将node.js请求包装到promise和piping中,javascript,node.js,promise,request,Javascript,Node.js,Promise,Request,以下是我的设想: 我想使用库获取一些外部资源(二进制文件),并通过管道将其传输到我自己应用程序的客户端。如果响应代码为!=200或到达远程服务器时出现问题,我想截获并提供自定义错误消息。理想情况下,若响应良好,我希望保留原始标题 我能够通过下面粘贴的第一段代码实现这一点。然而,我的整个应用程序都是基于Promise API的,所以我想让它保持一致,并将其包装在Promise中。当我这么做的时候,它就不起作用了。首先,我试图做到这一点,但没有成功。然后我试着自己准备一个非常简单的例子,但还是没有运

以下是我的设想: 我想使用库获取一些外部资源(二进制文件),并通过管道将其传输到我自己应用程序的客户端。如果响应代码为!=200或到达远程服务器时出现问题,我想截获并提供自定义错误消息。理想情况下,若响应良好,我希望保留原始标题

我能够通过下面粘贴的第一段代码实现这一点。然而,我的整个应用程序都是基于Promise API的,所以我想让它保持一致,并将其包装在Promise中。当我这么做的时候,它就不起作用了。首先,我试图做到这一点,但没有成功。然后我试着自己准备一个非常简单的例子,但还是没有运气

工作示例

var r = request.get('http://foo.bar');
r.on('response', result => {
  if (result.statusCode === 200) {
    r.pipe(res);
  } else {
    res.status(500).send('custom error message')
  }
});
r.on('error', error => res.status(500).send('custom error message');
var r;
return new Promise((resolve, reject) => {
  r = request.get('http://foo.bar');
  r.on('response', result => {
    if (result.statusCode === 200) {
      resolve();
    } else {
      reject()
    }
  });
  r.on('error', reject);
}).then(() => {
  r.pipe(res);
}).catch(() => {
  res.status(500).json('custom error message');
});
不起作用示例

var r = request.get('http://foo.bar');
r.on('response', result => {
  if (result.statusCode === 200) {
    r.pipe(res);
  } else {
    res.status(500).send('custom error message')
  }
});
r.on('error', error => res.status(500).send('custom error message');
var r;
return new Promise((resolve, reject) => {
  r = request.get('http://foo.bar');
  r.on('response', result => {
    if (result.statusCode === 200) {
      resolve();
    } else {
      reject()
    }
  });
  r.on('error', reject);
}).then(() => {
  r.pipe(res);
}).catch(() => {
  res.status(500).json('custom error message');
});
我所说的“不工作”是指没有响应,请求在超时之前处于挂起状态

我已将传递到
resolve
的结果改为调用
.pipe()
,而不是
r
。它响应客户机,但响应为空

最后,我尝试用简单的
http.get()
替换请求库。这样,服务器将文件返回给客户端,但缺少头(如
内容类型
内容长度


我在谷歌上搜索了很多,尝试了几个请求版本。。。问题是,当触发
“response”
时,您创建了一个立即解决的新承诺,但是
然后
回调总是异步执行,当调用它时,文件已到达服务器,并且不再有数据流过流。相反,您可以只使用回调函数的
body
参数:

request.get('http://foo.bar', function(request, response, body) {
  if(response.statusCode === 200) {
    res.end(body);
  } else {
    res.status(500).end();
  }
});
对于使用streams
request
似乎有点问题,
axios
似乎做得更好:

axios.get("http://foo.bar"', {
  validateStatus: status => status === 200,
  responseType: "stream"
}).then(({data: stream}) => {
  stream.pipe(res);
}).catch(error => {
   res.status(500).json(error);
});

问题是,当触发
“response”
时,您创建了一个立即解决的新承诺,但是
然后
回调总是异步执行的,当它被调用时,文件已经到达服务器,并且不再有数据流过流。相反,您可以只使用回调函数的
body
参数:

request.get('http://foo.bar', function(request, response, body) {
  if(response.statusCode === 200) {
    res.end(body);
  } else {
    res.status(500).end();
  }
});
对于使用streams
request
似乎有点问题,
axios
似乎做得更好:

axios.get("http://foo.bar"', {
  validateStatus: status => status === 200,
  responseType: "stream"
}).then(({data: stream}) => {
  stream.pipe(res);
}).catch(error => {
   res.status(500).json(error);
});


在解决承诺之前,您是否尝试过.pipe()?在管道中使用承诺有什么意义?他们的目的是相反的。管道允许不等待整个响应完成。是的,它可以工作。那么唯一的问题是当我想在
Then()
中插入管道时,我真正想要的是在应用程序的不同部分获得远程资源和管道,并且承诺会使分离变得容易。Estus,我不确定我是否正确理解你,但是。。。我想我必须等待,因为我想检查状态码?@xersiee理想情况下,你只想等待状态码,但一旦它在那里并且是2xx,你就不想等待整个响应到达,只需在数据进入时将其流式传输到目的地-所以原始方法对我来说很好!在解决承诺之前,您是否尝试过.pipe()?在管道中使用承诺有什么意义?他们的目的是相反的。管道允许不等待整个响应完成。是的,它可以工作。那么唯一的问题是当我想在
Then()
中插入管道时,我真正想要的是在应用程序的不同部分获得远程资源和管道,并且承诺会使分离变得容易。Estus,我不确定我是否正确理解你,但是。。。我想我必须等待,因为我想检查状态码?@xersiee理想情况下,你只想等待状态码,但一旦它在那里并且是2xx,你就不想等待整个响应到达,只需在数据进入时将其流式传输到目的地-所以原始方法对我来说很好!谢谢你的提示。我可能会去的。但有一个小问题需要跟进——如果您所写的是真的,那么为什么在触发
响应后也执行管道时,第一个示例中的所有操作都有效?您能否进一步解释为什么该代码不起作用?你的意思是说文件在注册
r.on('response',…)
之前就已经到达了?@dasfdsa这是由于承诺的异步性,我编辑了一些措辞precise@xersiee:在第一个示例中(无承诺),将立即调用
r.pipe
,而如果在解析承诺后调用它,它将出现在事件循环的下一轮中。似乎描述了一种类似的情况,即在解析承诺后调用
管道之前数据丢失。(
request
在这方面有很多未解决的问题-只要看看问题的数量和GitHub中打开的PRs,我建议考虑一个替代方案。)您还提到,
request promise
也不起作用-您尝试了什么?此答案中的解决方案失去了流式处理的好处:它首先将整个响应体加载到内存中,然后才将其发送到
res
,这可能是非常低效的,并且只有当数据的大小足够小时才足够好。(参见示例)感谢您的提示。我可能会去的。但有一个小问题需要跟进——如果您所写的是真的,那么为什么在触发
响应后也执行管道时,第一个示例中的所有操作都有效?您能否进一步解释为什么该代码不起作用?你的意思是说文件在注册
r.on('response',…)
之前就已经到达了?@dasfdsa这是由于承诺的异步性,我编辑了一些措辞precise@xersiee:在第一个示例中(无承诺),将立即调用
r.pipe
,而如果在解析承诺后调用它,它将出现在事件循环的下一轮中。似乎