nodejs - đối số đầu tiên phải là một chuỗi hoặc Bộ đệm - khi sử dụng response.write với http.request


92

Tôi chỉ đơn giản là đang cố gắng tạo một máy chủ nút xuất trạng thái HTTP của một URL nhất định.

Khi tôi cố gắng xóa phản hồi bằng res.write, tôi gặp lỗi: ném TypeError mới ('đối số đầu tiên phải là một chuỗi hoặc Bộ đệm');

Nhưng nếu tôi thay thế chúng bằng console.log, mọi thứ đều ổn (nhưng tôi cần ghi chúng vào trình duyệt chứ không phải giao diện điều khiển).

Mã là

var server = http.createServer(function (req, res) {
    res.writeHead(200, {"Content-Type": "text/plain"});

    request({
        uri: 'http://www.google.com',
        method: 'GET',
        maxRedirects:3
    }, function(error, response, body) {
        if (!error) {
            res.write(response.statusCode);
        } else {
            //response.end(error);
            res.write(error);
        }
    });     

    res.end();
});
server.listen(9999);

Tôi tin rằng tôi nên thêm một cuộc gọi lại ở đâu đó nhưng khá bối rối và mọi trợ giúp đều được đánh giá cao.

Câu trả lời:


31

Yêu cầu có một phương thức gọi lại, không đồng bộ của nó! Vì vậy, tôi giả sử, vào thời điểm lệnh gọi lại được thực thi, res.end()có thể sẽ được gọi. Thử đóng yêu cầu trong cuộc gọi lại.


1
Đã làm điều đó và cũng đã thêm .toString. Cảm ơn nhiều.
umutm

Có vẻ như tôi đã quên. Vừa mới làm. Cám ơn.
umutm 21/12/16

1
@umutm Có nhiều câu trả lời được viết tốt và trau chuốt hơn, có lẽ bạn nên chấp nhận một trong số chúng; làm cho nó hiển thị cho bất kỳ ai đến câu hỏi này.
Gaurav Agarwal

52

response.statusCodelà một số, ví dụ response.statusCode === 200, không phải '200'. Như thông báo lỗi cho biết, writemong đợi một stringhoặc Bufferđối tượng, vì vậy bạn phải chuyển đổi nó.

res.write(response.statusCode.toString());

Bạn cũng đúng về nhận xét gọi lại của mình. res.end();nên ở bên trong cuộc gọi lại, ngay bên dưới writecuộc gọi của bạn .


Vâng, đó là mẹo. Là một thành viên mới của nodejs, không biết điều đó và cảm ơn rất nhiều.
umutm

48

Tôi nhận được thông báo lỗi này và nó đề cập đến options.body

Tôi đã có cái này ban đầu

request.post({
    url: apiServerBaseUrl + '/v1/verify',
    body: {
        email: req.user.email
    }
});

Tôi đã thay đổi nó thành thế này:

request.post({
    url: apiServerBaseUrl + '/v1/verify',
    body: JSON.stringify({
        email: req.user.email
    })
});

và nó dường như hoạt động ngay bây giờ mà không có thông báo lỗi ... có vẻ như lỗi.

Tôi nghĩ đây là cách chính thức hơn để làm điều đó:

 request.post({
        url: apiServerBaseUrl + '/v1/verify',
        json: true,
        body: {
            email: req.user.email
        }
    });

4
Vấn đề của bạn là khác, theo mặc định, nội dung được mong đợi là một chuỗi hoặc Bộ đệm. Bạn cũng có thể thay đổi nó (thành json serializable) thêm json: true vào các tùy chọn. Ví dụ: request.post ({url: apiServerBaseUrl + '/ v1 / verify', body: {email: req.user.email}, json: true})
Nuno Tomas

2
Bạn có thể sử dụng điều này để tránh stringify javascript request.post({ url: apiServerBaseUrl + '/v1/verify', json: { email: req.user.email } }
bsorrentino

13

Rõ ràng là bạn đang cố gửi một thứ gì đó không phải là chuỗi hoặc bộ đệm. :) Nó hoạt động với console, vì console chấp nhận bất cứ thứ gì. Ví dụ đơn giản:

var obj = { test : "test" };
console.log( obj ); // works
res.write( obj ); // fails

Một cách để chuyển đổi bất kỳ thứ gì thành chuỗi là làm điều đó:

res.write( "" + obj );

bất cứ khi nào bạn đang cố gắng gửi một cái gì đó. Cách khác là gọi .toString()phương thức:

res.write( obj.toString( ) );

Lưu ý rằng nó vẫn có thể không phải là những gì bạn đang tìm kiếm. Bạn phải luôn chuyển chuỗi / bộ đệm đến .writemà không cần thủ thuật như vậy.

Lưu ý thêm: Tôi cho rằng đó requestlà một hoạt động không đồng bộ. Nếu đúng như vậy, thì res.end();sẽ được gọi trước bất kỳ lần viết nào, tức là mọi lần viết sẽ không thành công (vì kết nối sẽ bị đóng tại điểm đó). Di chuyển dòng đó vào trình xử lý:

request({
    uri: 'http://www.google.com',
    method: 'GET',
    maxRedirects:3
}, function(error, response, body) {
    if (!error) {
        res.write(response.statusCode);
    } else {
        //response.end(error);
        res.write(error);
    }
    res.end( );
});

Cảm ơn rất nhiều vì câu trả lời và thông tin chi tiết. Và, có, tôi đã chuyển res.end vào trình xử lý. Tôi đã chấp nhận @loganfsmyth như trước đó. Thx một lần nữa.
umutm

1

nếu bạn muốn ghi một đối tượng JSON vào phản hồi thì hãy thay đổi kiểu nội dung tiêu đề thành application / json

response.writeHead(200, {"Content-Type": "application/json"});
var d = new Date(parseURL.query.iso);
var postData = {
    "hour" : d.getHours(),
    "minute" : d.getMinutes(),
    "second" : d.getSeconds()
}
response.write(postData)
response.end();

1

Và có một khả năng khác (không phải trong trường hợp này) khi làm việc với ajax (XMLhttpRequest), trong khi gửi thông tin trở lại máy khách, bạn nên sử dụng res.send (responseetext) thay vì res.end (responsivext)


1

Mặc dù câu hỏi được giải quyết, chia sẻ kiến ​​thức để làm rõ nghĩa chính xác của lỗi.

Lỗi nói rằng tham số cần thiết cho hàm ngắt liên quan không ở định dạng bắt buộc, tức là chuỗi hoặc Bộ đệm

Giải pháp là thay đổi tham số thành chuỗi

breakingFunction(JSON.stringify(offendingParameter), ... other params...);

hoặc đệm

breakingFunction(BSON.serialize(offendingParameter), ... other params...);

0

Đối số đầu tiên phải là một trong loại chuỗi hoặc Bộ đệm. Đối tượng loại đã nhận

 at write_

Tôi gặp phải lỗi như trên khi chuyển dữ liệu nội dung vào mô-đun yêu cầu.

Tôi đã truyền một tham số khác là JSON: true và nó đang hoạt động.

var option={
url:"https://myfirstwebsite/v1/appdata",
json:true,
body:{name:'xyz',age:30},
headers://my credential
}
rp(option)
.then((res)=>{
res.send({response:res});})
.catch((error)=>{
res.send({response:error});})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.