Как я могу сделать этот вызов для запроса в nodejs синхронным? - PullRequest
19 голосов
/ 27 марта 2012

В моем приложении nodejs есть функция get_source_at.Он принимает URI в качестве аргумента, и его цель - вернуть исходный код из этого URI.Моя проблема в том, что я не знаю, как сделать функцию синхронно вызывать запрос, вместо того, чтобы дать ему эту функцию обратного вызова.Я хочу, чтобы поток управления остановился на несколько секунд, необходимых для загрузки URI.Как мне этого добиться?

function get_source_at(uri){
    var source;
    request({ uri:uri}, function (error, response, body) {
        console.log(body);
    });
    return source;
}

Кроме того, я читал о «событиях» и о том, как «выравнивается» узел, и я должен уважать это при написании своего кода.Я счастлив сделать это, но у меня должен быть способ убедиться, что у меня есть исходный код из URI, прежде чем продолжить поток управления моего приложения - так что если это не делается синхронной функцией, как это можно сделать

Ответы [ 6 ]

17 голосов
/ 24 декабря 2014

Вы можете с deasync :

function get_source_at(uri){
    var source;
    request({ uri:uri}, function (error, response, body) {
        source = body;
        console.log(body);
    });
    while(source === undefined) {
      require('deasync').runLoopOnce();
    }
    return source;
}
15 голосов
/ 27 марта 2012

Вам следует избегать синхронных запросов. Если вам нужно что-то вроде синхронного потока управления, вы можете использовать async .

async.waterfall([
    function(callback){
        data = get_source_at(uri);
        callback(null, data);
    },
    function(data,callback){
        process(data, callback);
    },
], function (err,result) {
    console.log(result)
});

process обещают запустить после возврата get_source_at.

9 голосов
/ 21 февраля 2016

Это лучший способ использования deasync.

var request = require("request")
var deasync = require("deasync")

var getHtml = deasync(function (url, cb) {
   var userAgent = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"}
   request({
      url: url, 
      headers: userAgent
   },
   function (err, resp, body) {
      if (err) { cb(err, null) }
      cb(null, body)
   })
})

var title = /<title>(.*?)<\/title>/

var myTitle = getHtml("http://www.yahoo.com").match(title)[1]
console.log(myTitle)

Пожалуйста, обратитесь к документации по deasync , вы найдете, что вы можете использовать
desync(function (n params, cb) {})
, чтобы сделать функцию , где cb должен вернуться с (err, data).Так что fs.readFile() подобные функции можно легко обернуть с помощью функции deasync.Но для таких функций, как request, которые не возвращаются с cb(err, data).Вы можете создать собственную функцию (именованную или анонимную) с пользовательским форматом обратного вызова cb(err, data), как я делал в приведенном выше коде.Таким образом, вы можете заставить почти любую асинхронную функцию работать как синхронизация, ожидая, когда обратный вызов cb(err, data) вернется на другой уровень javascript (как сказано в документации).Также убедитесь, что вы рассмотрели все способы выхода из функции, которую вы оборачиваете с помощью deasync с cb(err, data) обратными вызовами, в противном случае ваша программа заблокируется.

Надеюсь, это кому-то поможет!

Обновление:
Не используйте этот способ выполнения синхронных запросов.Используйте Async / Await для написания обещаний на основе синхронного кода.Вы можете использовать модуль request-promise-native npm, чтобы самостоятельно не связывать модуль запросов с обещаниями.

2 голосов
/ 20 декабря 2017

Наличие простой функции блокировки - отличная возможность для интерактивной разработки!Функция sync (определено ниже) может синхронизировать любое обещание, значительно сокращая количество синтаксиса, необходимого для игры с API и его изучения.Например, вот как это использовать с библиотекой puppeteer для Chrome без головы:

var browser = sync(puppeteer.connect({ browserWSEndpoint: "ws://some-endpoint"}));
var pages = sync(browser.pages())
pages.length
1
var page = pages[0]
sync(page.goto('https://duckduckgo.com', {waitUntil: 'networkidle2'}))
sync(page.pdf({path: 'webpage.pdf', format: 'A4'}))

Самое приятное то, что каждая из этих строк может быть настроена, пока она не выполнит то, что вы хотитебез необходимости перезапуска или повторного ввода всех предыдущих строк каждый раз, когда вы хотите проверить это.Это работает, потому что у вас есть прямой доступ к переменным browser и pages с верхнего уровня.

Вот как это работает:

const deasync = require("deasync");
const sync = deasync((promise, callback) => promise.then(result) => callback(null, result)));

Используется deasync пакет упоминается в других ответах.deasync создает частичное приложение к анонимной функции, которая добавляет callback в качестве последнего аргумента и блокирует, пока не будет вызван callback.callback получает условие ошибки в качестве первого аргумента (если есть) и результат в качестве второго (если есть).

1 голос
/ 27 марта 2012

У меня должен быть способ убедиться, что у меня есть исходный код из URI, прежде чем продолжить поток управления моим приложением - так что, если это не делается синхронной функцией, как это можно сделать?

Учитывая эту точку входа в ваше приложение:

function app(body) {
    // Doing lots of rad stuff
}

Вы начинаете, беря тело:

request({ uri: uri }, function (error, response, body) {
    if(err) return console.error(err);

    // Start application
    app(body);
}

Это то, к чему вы должны привыкнуть при программировании для node.js (и javascript в целом). Существуют модули потока управления, такие как async (которые я тоже рекомендую), но вы должны привыкнуть к продолжению стиля передачи , как его называют.

0 голосов
/ 27 марта 2012

Хорошо, во-первых, чтобы сохранить этот код асинхронным, вы можете просто поместить соответствующий код в обратный вызов функции запроса, что означает, что он будет выполняться после завершения запроса, но не остановит процессор от обработки других задач в вашем приложении.Если вам это нужно несколько раз, я бы посоветовал вам проверить Синхронный запрос в Node.js , в котором описываются различные методы, чтобы сделать это более упорядоченным, и обсуждаются различные библиотеки потоков управления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...