2016-08-06 3 views
0

안녕하세요 저는 여기서 약간 이상한 것을하려고합니다. 비동기와 동기화를 함께 사용하는 것이므로 예상대로 작동하지 않습니다. 현재 배열에서 3 명의 사용자가 실행되면 배열의 사용자 이름 전체에 대해 어떻게 실행합니까?비동기식/동기식 루핑 Node.js

var i = 0, 
fs = require('fs'), 
fetch = require('node-fetch'); 

fs.readFile('file.txt', function(err, data) { 
    var array = data.toString().split("\n"); 
    getCreationDate(array); 
}); 

function getCreationDate(array) { 
    fetch('http://mytwitterbirthday.com/api/?screen_name=' + array[i]) 
    .then(function(res) { 
    return res.json(); 
    }).then(function(json) { 
    console.log(i, array[i]) 
    console.log(json[0].screen_name, json[0].created_at); 
    }).then(function() { 
    i++; 
    getCreationDate(array); 
    }) 
} 

답변

0

출력과 같은 순서로 출력 할 필요가 없다고 가정합니다. 이 경우 getCreationDate()을 변경하여 단일 이름과 해당 색인을 허용 할 수 있습니다.

function getCreationDate(name, i) { 
    fetch('http://mytwitterbirthday.com/api/?screen_name=' + name) 
    .then(function(res) { 
    var json = res.json(); 
    console.log(i, name) 
    console.log(json[0].screen_name, json[0].created_at); 
    }); 
} 

이제 배열의 각 항목에 대해 위 함수를 호출하십시오.

array.forEach(getCreationDate); 
+0

참고 :이 한 번에 모든 요청을 시작합니다 (병렬 - 그 속도 제한을 위해 중요한 경우 원래의 코드는 직렬을하고 있던 반면)와 C 결과를 순서대로 얻거나 모든 결과가 언제 나오는지 알고 싶다면 ode를 추가해야합니다. 이것은 그 자체로는 정말로 유용하지 않습니다. 해결책의 한 부분 일뿐입니다. – jfriend00

+0

이것은 '대기열 소비자'가 아니며 한 번에 각 요청을 실행합니다. – Hitmands

+0

@Hitmands : 예, 대답에서 : "배열과 같은 순서로 출력물을 인쇄 할 필요가 없다고 가정합니다." – thameera

0

아마도 도움이 될 수 있습니다 ... 당신은 캐치를 놓쳤습니다.

const 
 
    fs = require('fs'), 
 
    fetch = require('node-fetch') 
 
; 
 

 
(new Promise((res, rej) => { 
 
    fs.readFile('file.txt', (err, data) => { 
 
    if(err) { 
 
     return rej(err); 
 
    } 
 
    
 
    return resolve(data.toString().split('\n')); 
 
    }); 
 
})) 
 
    .then(data => doSomething(data, 0)) 
 
    .catch(error => console.error.bind(console)) 
 
; 
 

 
function doSomething(data, index) { 
 
    const API = 'http://mytwitterbirthday.com/api/'; 
 
    const MAX_ERRORS = 3; // or what you want 
 
    let errors = 0; 
 
    
 
    return fetch(`${API}?screen_name=${data[index]}`) 
 
    .then(r => r.json()) 
 
    .then(response => { 
 
     console.log("response", response); 
 
    }) 
 
    .then(() => doSomething(data, ++index)) 
 
    .catch(error => { 
 
     if(MAX_ERRORS <= errors) { 
 
     console.log('giving up', {errors}); 
 
     return; 
 
     } 
 
     
 
     errors += 1; 
 
     return doSomething(data, index); 
 
    }) 
 
    ; 
 
};

허용 대답은 다음과 제공하지 않기 때문에 내가 다른 대답을 추가합니다
0

:

  1. 알림 모든 요청이
  2. 순서
  3. 에 결과를 제공 할 때
  4. 오류 처리
  5. 동시에 실행되는 요청 수를 결정할 수있는 동시성 제어 (트위터 비율 제한에 중요 할 수 있음)

이 첫 번째 솔루션은 일을 크게 단순화하기 때문에 Bluebird 약속 라이브러리를 사용합니다. 특히 동시성 제어를위한 트위터는 한 번에 모든 요청을 전송 괜찮 경우,

const fs = require('fs'); 
const fetch = require('node-fetch); 

// promisify readFile 
fs.readFileAsync = function(file, options) { 
    return new Promise(function(resolve, reject) { 
     fs.readFile(file, options, function(err, data) { 
      if (err) return reject(err); 
      resolve(data); 
     }); 
    }); 
} 

function getSingleCreationDate(item) { 
    return fetch('http://mytwitterbirthday.com/api/?screen_name=' + item).then(function(response) { 
     return response.json(); 
    }); 
} 

function getAllCreationDates(file) { 
    return fs.readFileAsync(file).then(function(data) { 
     let array = data.toString().split("\n"); 
     let results = []; 
     return array.reduce(function(p, item) { 
      return p.then(function() { 
       return getSingleCreationDate(item).then(function(twitterData) { 
        results.push(twitterData); 
       }); 
      }) 
     }, Promise.resolve()).then(function() { 
      // make array of results be the resolved value 
      return results; 
     }); 
    }); 
} 

getAllCreationDates('file.txt').then(function(results) { 
    // process array of results here (in order) 
}).catch(function(err) { 
    // handle error here 
}); 

또는 :

const Promise = require('bluebird'); 
const fs = Promise.promsifyAll(require('fs')); 
const fetch = require('node-fetch); 

function getSingleCreationDate(item) { 
    return fetch('http://mytwitterbirthday.com/api/?screen_name=' + item).then(function(response) { 
     return response.json(); 
    }); 
} 

function getAllCreationDates(file) { 
    return fs.readFileAsync(file).then(function(data) { 
     let array = data.toString().split("\n"); 
     // put whatever concurrency value here works best, higher is more parallelism 
     // lower is more protection from being rate limited by the host 
     return Promise.map(array, getSingleCreationDate, {concurrency: 4}); 
    }); 
} 

getAllCreationDates('file.txt').then(function(results) { 
    // process array of results here (in order) 
}).catch(function(err) { 
    // handle error here 
}); 

이 두 번째 솔루션은 표준 ES6의 약속을 사용하고 영업 이익의 원본 코드와 같은 요청을 직렬화 이 작업을 수행 할 수 있습니다

const fs = require('fs'); 
const fetch = require('node-fetch); 

// promisify readFile 
fs.readFileAsync = function(file, options) { 
    return new Promise(function(resolve, reject) { 
     fs.readFile(file, options, function(err, data) { 
      if (err) return reject(err); 
      resolve(data); 
     }); 
    }); 
} 

function getSingleCreationDate(item) { 
    return fetch('http://mytwitterbirthday.com/api/?screen_name=' + item).then(function(response) { 
     return response.json(); 
    }); 
} 

function getAllCreationDates(file) { 
    return fs.readFileAsync(file).then(function(data) { 
     let array = data.toString().split("\n"); 
     return Promise.all(array.map(function(item) { 
      return getSingleCreationDate(item); 
     })); 
    }); 
} 

getAllCreationDates('file.txt').then(function(results) { 
    // process array of results here (in order) 
}).catch(function(err) { 
    // handle error here 
});