2012-03-27 4 views
17

내 nodejs 응용 프로그램에 get_source_at이라는 함수가 있습니다. 그것은 uri를 인수로 취하며 그 목적은 uri에서 소스 코드를 반환하는 것입니다. 내 문제는 함수를 동 기적으로 요청을 호출하는 대신 콜백 함수를 제공하는 방법을 모르는 것이다. I 은 uri를로드하는 데 걸리는 몇 초 동안 제어 흐름이 중지되도록을 원합니다. 이것을 어떻게 할 수 있습니까?nodejs에서이 호출을 동기 화하려면 어떻게해야합니까?

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

또한 '이벤트'및 노드가 '이벤트 발생'방식을 읽었으며 코드 작성시이를 존중해야합니다. 그 일을하게되어 기쁩니다.하지만 애플리케이션의 제어 흐름을 계속하기 전에 uri의 소스 코드가 있는지 확인해야합니다. 따라서 함수를 동기식으로 만들지 않으면 어떻게 할 수 있습니까? ?

+0

Lai의 답변이 기술적으로 정확하므로 (답변으로 표시 했으므로) 궁극적 인 해결책은 더 많은 작업이 필요했습니다. https://gist.github.com/2234466에있는 샘플 코드의 패턴을 사용할 수 있습니다. – Trindaz

답변

16

동기 요청을 피하십시오. 동기 제어 흐름과 같은 것을 원하면 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의 복귀 후 을 실행하기로 약속한다.

+16

"동기식 요청을 피해야합니다."는 정확한 담요 진술이 아닙니다. 응용 프로그램의 주 스레드에서 수행되는 동기 요청이나 UI가 차단되는 상황에서 발생하는 동기 요청을 피하십시오. 그러나 말하자면, headless webservice는 다른 웹 서비스에 위임하고 그 결과를보고하는 것이 목적 일뿐입니다. 거기에 동기 요청은 완벽하게 좋으며 실제로는 비동기 요청보다 바람직합니다. 유스 케이스를 이해하고 가장 적합한 솔루션을 선택하는 것이 중요합니다. 그것은 언제나 하나가 아니라 다른 것의 경우가 아닙니다. – aroth

+1

@aroth와 동의하십시오 - 모든 명령을 엄격한 순서로 실행해야하는 사용자 정의 복잡한 배포 작업을 위해 nodejs 스크립트를 사용하고 있습니다. 나는 약속을 사용할 수는 있지만 엄격한 순서로 실행하는 작업이 10 개를 초과하는 경우 'then()'체인을 사용하면 다소 못 생길 수 있습니다. – JustAMartin

+0

이 질문에 대한 답변이 아닙니다. –

0

우선, 해당 코드를 비동기로 유지하려면 관련 코드를 요청 함수의 콜백 내에두면됩니다. 즉, 요청이 완료된 후에 실행되지만 응용 프로그램에서 다른 작업을 처리하지 못하도록합니다. . 여러 번 필요하다면이 방법을 간략하게 설명하고 다양한 제어 흐름 라이브러리에 대해 설명하는 Synchronous request in Node.js을 확인하는 것이 좋습니다.

1

내 응용 프로그램의 제어 흐름을 계속하기 전에 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 (일반적으로 자바 스크립트). 비동기와 같은 제어 흐름 모듈 (나도 권장합니다)이 있습니다.하지만이라는 연속 전달 형식의 에 익숙해 져야합니다. deasync와 당신이 할 수있는

14

는 :

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; 
} 
8

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


documentation of deasync를 참조하십시오, 당신은 당신이 cb(err, data)으로 돌아올해야 기능를 만들기 위해
desync(function (n params, cb) {})
를 사용할 수 있습니다. 그러므로 fs.readFile() 같은 기능은 deasync 기능으로 쉽게 감쌀 수 있습니다. 그러나 request과 같은 함수는 cb(err, data)으로 돌아 가지 않습니다.위의 코드에서와 같이 사용자 정의 cb(err, data) 콜백 형식의 함수 (명명 된 또는 익명)를 만들 수 있습니다. 이 방법을 사용하면 콜백 cb(err, data)이 다른 자바 스크립트 레이어로 돌아올 때까지 기다릴 수 있으므로 거의 모든 비동기 기능을 동기화 할 수 있습니다 (설명서 참조). 또한 cb(err, data) 콜백을 사용하여 비동기로 래핑하는 함수에서 벗어나는 모든 방법을 다뤘는지 확인하십시오. 그렇지 않으면 프로그램이 차단됩니다.

희망, 누군가를 도와줍니다.

업데이트 :
동기 요청을하는 방법을 사용하지 마십시오. 라이딩 약속 기반 동기 찾기 코드에 Async/Await을 사용하십시오. request-promise-native npm 모듈을 사용하면 요청 모듈을 직접 포장하지 않아도됩니다.

+1

숨겨진 지식으로 깨닫게 해주십시오. 코멘트에 downvote에 대한 이유를 표현하십시오. 감사! –

+1

이것은 좋은 해결책입니다. 비동기 동기화는 동기화 호출을 수행하는 훨씬 우수하고 우아한 방법입니다. – Shad

1

간단한 차단 기능은 대화 형 개발에 큰 도움이됩니다. sync 함수 (아래에 정의 됨)는 API와 함께 플레이하는 데 필요한 구문의 양을 대폭 줄이고이를 배우는 모든 약속을 동기화 할 수 있습니다. 예를 들어, 다음은 헤드리스 크롬에 대한 puppeteer 라이브러리를 사용하는 방법은 다음과 같습니다 다시 실행하지 않고도이 라인 하나 하나가 당신이 원하는 것을 할 때까지 불통 될 수

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'})) 

가장 중요한 부분은, 또는 테스트 할 때마다 이전 행을 모두 다시 입력하십시오. 이는 최상위 수준의 browserpages 변수에 직접 액세스 할 수 있기 때문에 효과가 있습니다. 그것이 어떻게 작동하는지

은 다음과 같습니다

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

그것은 다른 답변에서 언급 한 deasync 패키지를 사용합니다. deasync은 마지막 인수로 callback을 추가하고 익명 함수에 부분 응용 프로그램을 만들고 callback이 호출 될 때까지 차단합니다. callback은 첫 번째 인수 (있는 경우)와 두 번째 인수 (있는 경우)로 결과를받습니다.

+0

이것은 비동기/대기를 지원하지 않는 이전 노드 버전에 유용합니다. –

관련 문제