2017-11-25 1 views
0

요청시 콜백 함수를 순서대로 실행하는 방법을 알아 내려고하고 있습니다. 현재 루프는 10 번 실행되지만 콜백 함수가 끝날 때까지 기다리지 않고 다음 반복으로 이동합니다. 내 결과물은 내가 기대했던 것만 큼 다르지 않다. 왜 어떤 것들이 다른 것들보다 먼저 인쇄되고 있는지 나는 잘 모르겠다. 여기 내 코드는 현재로서는 방법입니다 : 여기 nodejs request가 마지막으로 실행 중입니다.

var express = require('express'); 
var path = require('path'); 
var request = require('request'); 
var cheerio = require('cheerio'); 
var fs = require('fs'); 
var app = express(); 
var url; 
for(var i=0; i < 10; i++){ 
    url = "http://www.ratemyprofessors.com/ShowRatings.jsp?tid=" + i; 
    request(url, function(err, resp, body){ 
     console.log("hello"); 
     var $ = cheerio.load(body); 
     if($('.error').text().substring(0, 14) == "Page Not Found"){ 
      console.log("sorry page not found"); 
      return; 
     }else{ 
     console.log($('.error').text().substring(0, 14)); 
     var pfname = $('.pfname'); 
     var plname = $('.plname'); 
     var professorName = pfname.text().replace(/\s/g, '') + " " +plname.text().replace(/\s/g, ''); 
     console.log(professorName); 
     console.log(url); 
     return; 
     } 

    }); 
} 

내가 무엇입니까 출력입니다 :

hello 
    sorry page not found 
    hello 
    sorry page not found 
    hello 
    sorry page not found 
    hello 
    sorry page not found 
    hello 
    sorry page not found 
    hello 
    sorry page not found 
    hello 
    sorry page not found 
    hello 

    Michael Beeson 
    http://www.ratemyprofessors.com/ShowRatings.jsp?tid=9 
    hello 

    Sami Khuri 
    http://www.ratemyprofessors.com/ShowRatings.jsp?tid=9 
    hello 

    aaa aaa 
    http://www.ratemyprofessors.com/ShowRatings.jsp?tid=9 

Here is the proper output: 


aaa aaa 
http://www.ratemyprofessors.com/ShowRatings.jsp?tid=1 

Sami Khuri 
http://www.ratemyprofessors.com/ShowRatings.jsp?tid=2 


Michael Beeson 
http://www.ratemyprofessors.com/ShowRatings.jsp?tid=3 

sorry page not found 
sorry page not found 
sorry page not found 
sorry page not found 
sorry page not found 
sorry page not found 
sorry page not found 

답변

3

이 코드에서 여러 문제가 있지만 주요 문제는 실행중인 것입니다 for 루프 내부에서 비동기 작업을 수행하므로 for 루프가 모든 비동기 작업을 시작하고 나중에 하나씩 완료됩니다. 루프 호출간에 공유되는 변수는 서로 트롬 프합니다.

그래서, 간단히 말해서, 내가 그랬어 :

  1. 제거 된 모든 공유 변수 각각의 루프 호출은 자신의 변수 (충돌없이)가 있습니다.
  2. 요청이 약속으로 전환되었으므로 Promise.all()을 사용하여 모두 완료되면 더 쉽게 알려줄 수 있습니다.
  3. .then() 처리기에서 원하는 값을 반환하므로 루프가 호출 될 때마다 최종 값으로 Promise.all()이 수집됩니다.
  4. 작업을 시퀀싱 할 이유가 없기 때문에 모든 작업을 병렬 처리 (더 빠름)하고 나서 Promise.all() 결과를 최종 결과 배열에 순서대로 놓습니다. 여기

코드입니다 :

const express = require('express'); 
const path = require('path'); 
const rp = require('request-promise'); 
const cheerio = require('cheerio'); 
const fs = require('fs'); 
const app = express(); 

let promises = []; 
for (let i = 0; i < 10; i++) { 
    let url = "http://www.ratemyprofessors.com/ShowRatings.jsp?tid=" + i; 
    promises.push(rp(url).then(function(body) { 
     console.log(url); 
     let $ = cheerio.load(body); 
     if($('.error').text().substring(0, 14) == "Page Not Found"){ 
      console.log("sorry page not found"); 
      return null; 
     } else { 
      console.log($('.error').text().substring(0, 14)); 
      let pfname = $('.pfname'); 
      let plname = $('.plname'); 
      let professorName = pfname.text().replace(/\s/g, '') + " " +plname.text().replace(/\s/g, ''); 
      console.log(professorName); 
      return professorName; 
     } 

    })); 
} 

// see when they are all done 
Promise.all(promises).then(results => { 
    // array of results, some entries that were not found may be null 
    console.log(results); 
}).catch(err => { 
    console.log(err); 
}); 

두 번째 요청이 첫 번째가 완료 될 때까지, 즉이 async/await를 사용하는 것처럼 수행 할 수 시작되지 않도록 한 번에 하나씩 시퀀스하려는 경우 :

const express = require('express'); 
const path = require('path'); 
const rp = require('request-promise'); 
const cheerio = require('cheerio'); 
const fs = require('fs'); 
const app = express(); 

async function run() { 
    let results = []; 
    for (let i = 0; i < 10; i++) { 
     let url = "http://www.ratemyprofessors.com/ShowRatings.jsp?tid=" + i; 
     try { 
      let body = await rp(url); 
      console.log("hello"); 
      let $ = cheerio.load(body); 
      if($('.error').text().substring(0, 14) == "Page Not Found"){ 
       console.log("sorry page not found"); 
       results.push(null); 
      } else { 
       console.log($('.error').text().substring(0, 14)); 
       let pfname = $('.pfname'); 
       let plname = $('.plname'); 
       let professorName = pfname.text().replace(/\s/g, '') + " " +plname.text().replace(/\s/g, ''); 
       console.log(professorName); 
       console.log(url); 
       results.push(professorName); 
      } 

     } catch(e) { 
      console.log(url, e); 
      results.push(null); 
     } 
    } 
    return results; 
} 

run().then(results => { 
    console.log(results); 
}).catch(err => { 
    console.log(err); 
});