chai-http 结束后写入

chai-http write after end

我有一个 server-app 从客户端接收音频流。我正在尝试使用 chai/chai-http 测试应用程序,但它给我这个错误:

[Error: write after end]

有什么问题?

代码:

var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('../server-app');
var should = chai.should();
var fs = require('fs');

chai.use(chaiHttp);


describe('server', function() {
  it('should work..', function (done){
    var req = chai.request(server).post('/speech');
    fs.createReadStream('./test.wav').pipe(req);
    req.end(function (err,res){
        console.log(err);//outputs: [Error: write after end]
        done();
    });
  });
});

您在流完成将数据推送到请求之前调用 req.end

我会做以下事情:

var readstream = fs.createReadStream('./test.wav');
readstream.pipe(req);

readstream.on('close', someFunction);
readstream.on('end', someFunction);

并在流的 closeend 事件中调用 req.end。您在发出这些事件中的任何一个之前调用 req.end。

基本上JavaScript是异步的,流或套接字连接是同步的,一旦你创建了一个流,你必须等待流关闭才能发出另一个请求

在你的例子中,一旦你打开流req.end就会执行

三个选项可使其正常工作

  1. 试试 chai agent
  2. 将您的代码放在流关闭中,因为 chai.end 和流结束对于您的场景来说似乎是相同的
  3. 将 req.end 放入 setTimeOut 中(未尝试可能是最坏的情况)

当管道时,默认情况下,当源流发出 'end' 事件时,在目标上调用 end()。所以你不必自己打电话给end()

订阅目标流的 'finish''error' 事件以控制何时完成工作或何时发生错误:

 fs.createReadStream('./test.wav').pipe(req);
 req.on('error', (err) => {console.log(err);});
 req.on('finish',() => {done();});

如果你想让编写器 (req) 保持打开状态,你可以在管道传输时将 end option 设置为 false:

fs.createReadStream('./test.wav').pipe(req, options = {end = false}); 但请记住 'finish' 事件不会被管道触发。