nodejs - перший аргумент повинен бути рядком або буфером - при використанні response.write із http.request


92

Я просто намагаюся створити сервер вузлів, який виводить статус HTTP даної URL-адреси.

Коли я намагаюся змити відповідь res.write, я отримую помилку: throw new TypeError ('перший аргумент повинен бути рядком або буфером');

Але якщо я заміню їх на console.log, все добре (але мені потрібно писати їх у браузер, а не в консоль).

Код такий

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);

Я вважаю, що я повинен десь додати зворотний дзвінок, але досить розгублений, і будь-яка допомога буде вдячна.

Відповіді:


31

Запит використовує метод зворотного виклику, його асинхронізацію! Тому я припускаю, що до моменту виконання зворотного виклику res.end()може бути викликаний. Спробуйте закрити запит у межах зворотного дзвінка.


1
Зробив це, а також додав .toString. Велике спасибі.
umutm

Здається, я забув. Просто зробив це. Дякую.
umutm

1
@umutm Є більше добре написаних та детально розроблених відповідей, напевно, слід прийняти одну з них; зробити його видимим для кожного, хто приходить до цього питання.
Gaurav Agarwal

52

response.statusCodeє числом, наприклад response.statusCode === 200, ні '200'. Як повідомляється в повідомленні про помилку, writeочікується a stringабо Bufferоб'єкт, тому його потрібно перетворити.

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

Ви також правильно вказали коментар зворотного дзвінка. res.end();має бути всередині зворотного дзвінка, трохи нижче ваших writeдзвінків.


Так, це зробило трюк. Як новачок nodejs, цього не знав і дякую.
umutm

48

Я отримую це повідомлення про помилку, і в ньому згадується options.body

У мене це було спочатку

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

Я змінив його на це:

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

і це, здається, працює зараз без повідомлення про помилку ... схоже на помилку.

Я думаю, що це більш офіційний спосіб зробити це:

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

4
Ваша проблема інша, за замовчуванням основним елементом є рядок або буфер. Ви також можете змінити його (щоб json можна було серіалізувати), додавши json: true до опцій. Наприклад: request.post ({url: apiServerBaseUrl + '/ v1 / verify', body: {email: req.user.email}, json: true})
Нуно Томас

2
Ви можете використовувати це , щоб уникнути stringify javascript request.post({ url: apiServerBaseUrl + '/v1/verify', json: { email: req.user.email } }
bsorrentino

13

Ну, очевидно, ви намагаєтеся надіслати щось, що не є рядком або буфером. :) Це працює з консоллю, оскільки консоль приймає що завгодно. Простий приклад:

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

Один із способів перетворити що-небудь на рядок - це зробити:

res.write( "" + obj );

щоразу, коли ви намагаєтесь щось надіслати. Інший спосіб - викликати .toString()метод:

res.write( obj.toString( ) );

Зверніть увагу, що це все одно може бути не тим, що ви шукаєте. Ви завжди повинні передавати рядки / буфери .writeбез таких хитрощів.

Як додаткове зауваження: я припускаю, що requestце асинхронна операція. Якщо це так, тоді res.end();буде викликано перед будь-яким записом, тобто будь-яке написання все одно зазнає невдачі (оскільки зв’язок буде закрито в цей момент). Перемістіть цей рядок у обробник:

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( );
});

Щиро дякую за відповідь та детальну інформацію. І так, я перемістив res.end у обробник. Я прийняв @loganfsmyth, як це було раніше. Знову Thx.
umutm

1

якщо ви хочете написати об'єкт JSON у відповідь, то змініть тип вмісту заголовка на 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

І є ще одна можливість (не в цьому випадку) при роботі з ajax (XMLhttpRequest), під час надсилання інформації назад до кінця клієнта ви повинні використовувати res.send (responsetext) замість res.end (responsetext)


1

Хоча питання вирішено, обмін знаннями для з’ясування правильного значення помилки.

Помилка говорить про те, що параметр, необхідний для відповідної функції злому, не у необхідному форматі, тобто рядок або буфер

Рішення - змінити параметр на рядок

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

або буфер

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

0

Перший аргумент повинен бути аргументом типу string або Buffer. Отриманий об’єкт типу

 at write_

Я отримував подібну вище помилку під час передачі даних тіла модулю запиту.

Я передав ще один параметр, який є JSON: true і працює.

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});})
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.