2016-08-06 11 views
0

Привет Я пытаюсь сделать что-то странное здесь, это как бы перемешивание асинхронно и синхронно, поэтому почему он не работает, как я ожидал. В настоящее время выполняется для 3 пользователей из массива, а затем заканчивается, как я могу заставить это работать для всей длины имен пользователей в массиве?Асинхронный/синхронный Looping 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. Любой контроль параллелизма, чтобы решить, сколько запросов выполняется одновременно (может быть важно для ограничения скорости твиттера)

Это первое решение использует библиотеку обещаний Bluebird, потому что это значительно упрощает ситуацию. в частности, для управления параллелизмом:

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 обещания и упорядочивает запросы как исходный код в OP в:

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