我需要映射一个具有4000个位置的数组,并且需要在Promise中运行此映射,但是我无法做到这一点:@
代码做什么? 我去MongoDB并获取了我需要的所有数据:
const axios = require('axios');
const cheerio = require('cheerio');
const MongoClient = require('mongodb').MongoClient;
const rp = require('request-promise');
let mongoConnection = 'connectionString';
let urlstations = [];
const mongoData = () => {
let res = new Promise( (resolve, reject ) => {
MongoClient.connect(mongoConnection, ( err, connection ) => {
if( err ){
console.log(err.message)
return reject(err);
}
let db = connection.db('atlas');
let query = { "Status": 1 };
let mysort = { "Broadcast": 1 };
db.collection("stations").find(query).limit(10).sort(mysort).toArray( ( err, result ) => {
if ( err ) throw err;
result.map( ( obj ) => {
urlstations.push({'_id': `${obj._id}`, 'url':`${obj.Broadcast}`, 'location': `${obj.Name} ${obj.Module} (${obj.Frequency}) ${obj.uf} | ${obj.cityName}`});
});
resolve(urlstations);
connection.close();
});
});
});
return res;
};
在那之后,我清理了所有仅获取HTTP或HTTPS的URL,并清理了端口之后的所有内容。
const jsonEdit = ( result ) => {
let res = new Promise( ( resolve, reject ) => {
result.map( ( obj, i ) => {
let string = JSON.stringify( obj.url );
if( string.includes('http') ){
let prefix = obj.url.split('//')[0];
let cleanString = obj.url.replace(/https?:\/\//gi, '');
urlstations[i].url = prefix + '//' + cleanString.split('/')[0];
} else {
delete urlstations[i];
};
});
resolve(urlstations);
})
return res;
};
直到这里,一切都按预期工作,现在我遇到了真正的问题:
我正在使用地图浏览我的数组(网址站),并使用Request-Promise npm包从对象获取属性网址,以访问互联网上的页面并获取XML信息并更新我的urlstations数组,但是如果您看到我下面的“主”函数,在地图后有一个console.log(),它总是在打印旧数组而不是新数组。
const createUrl = ( urlstations ) => {
let res = new Promise( ( resolve, reject ) => {
urlstations.map( ( obj, i ) => {
rp(obj.url + '/stats').then( ( xml ) => {
const $ = cheerio.load( xml, {
xmlMode: true
});
urlstations[i].url = obj.url + '/stats';
urlstations[i].uniquelisteners = `'${$('UNIQUELISTENERS').text()}'`;
urlstations[i].averagetime = `'${$('AVERAGETIME').text()}'`;
urlstations[i].servergenre = `'${$('SERVERGENRE').text()}'`;
urlstations[i].serverurl = `'${$('SERVERURL').text()}'`;
urlstations[i].songtitle = `'${$('SONGTITLE').text()}'`;
urlstations[i].streamhits = `'${$('STREAMHITS').text()}'`;
urlstations[i].streamuptime = `'${$('STREAMUPTIME').text()}'`;
console.log(urlstations[i])
}).catch( ( err ) => {
axios.get( obj.url + '/status-json.xsl').then( ( json ) => {
const $ = cheerio.load( json );
urlstations[i].url = obj.url + '/status-json.xsl';
urlstations[i].genre = `'${json.data.icestats.source.genre}'`;
urlstations[i].listeners = `'${json.data.icestats.source.listeners}'`;
urlstations[i].server_url = `'${json.data.icestats.source.server_url}'`;
urlstations[i].listenurl = `'${json.data.icestats.source.listenurl}'`;
console.log(urlstations[i]);
}).catch( ( err ) => {
})
});
console.log(i)
if( urlstations[i+1] == undefined){
resolve(urlstations)
}
});
});
return res;
};
const master = async () => {
let result = await mongoData();
result = await jsonEdit(result);
result = await createUrl(result);
await console.log(urlstations)
}
master();
去Mongo时我拥有什么样的阵列:
{ _id: '6464',
url: 'http://01.bitstreaming.info:8240/stream',
location: 'Itabaianinha FM (104.9) SE | Itabaianinha' },
{ _id: '3400',
url: 'http://01.bitstreaming.info:8304/stream',
location: 'Princesa FM (105.9) CE | Sobral' },
{ _id: '7780',
url: 'http://01.bitstreaming.info:8334/;stream.mp3',
location: 'Kompleta FM (96.7) GO | Jussara' }
我期望这个最后一个控制台向我显示:
{ _id: '3400',
url: 'http://01.bitstreaming.info:8304/stats',
location: 'Princesa FM (105.9) CE | Sobral',
uniquelisteners: '\'4\'',
averagetime: '\'3943\'',
servergenre: '\'Various\'',
serverurl: '\'http://www.radiofmprincesa.com\'',
songtitle: '\'O sucesso comeca aqui!\'',
streamhits: '\'311354\'',
streamuptime: '\'57178\'' }
{ _id: '7780',
url: 'http://01.bitstreaming.info:8334/stats',
location: 'Kompleta FM (96.7) GO | Jussara',
uniquelisteners: '\'6\'',
averagetime: '\'1886\'',
servergenre: '\'Various\'',
serverurl: '\'http://www.kompletafm.net\'',
songtitle: '\'\'',
streamhits: '\'174277\'',
streamuptime: '\'57168\'' }
我尝试使用Promise.all(https://flaviocopes.com/javascript-async-await-array-map/)并没有成功。 还有其他尝试,大约需要2到3天的时间。
答案 0 :(得分:0)
如果不是必须的话,不要创建新的Promises。只需使用已经存在的诺言并将它们结合起来即可:
const createUrl = urlstations => {
// Just return the promise chain:
// and use Promise.all to wait for all requests to complete
return Promise.all(urlstations.map(async (obj, i) => { // using async / await here helps cleaning up the code
try {
const xml = await rp(obj.url + '/stats');
const $ = cheerio.load( xml, {
xmlMode: true
});
Object.assign(obj, { // although not related to the problem, I prefer this as it removes some repetetive accessors
url: obj.url + '/stats',
uniquelisteners: `'${$('UNIQUELISTENERS').text()}'`,
averagetime: `'${$('AVERAGETIME').text()}'`,
servergenre: `'${$('SERVERGENRE').text()}'`,
serverurl: `'${$('SERVERURL').text()}'`,
songtitle: `'${$('SONGTITLE').text()}'`,
streamhits: `'${$('STREAMHITS').text()}'`,
streamuptime: `'${$('STREAMUPTIME').text()}'`,
});
} catch(error) {
//...
}
})).then(() => urlstations); // the returned result is the urlstations array
};
答案 1 :(得分:0)
map不会更新您现有的数组,它会返回一个应该分配给变量的新数组。 您还可以使用promise.all并在map函数中返回一个新对象,而不是尝试在循环内修改数组
改为尝试
const createUrl = (urlstations) => {
return Promise.all(
urlstations.map((obj, i) => {
return rp(obj.url + '/stats').then((xml) => {
const $ = cheerio.load(xml, {
xmlMode: true
})
return {
url: obj.url + '/stats',
uniquelisteners: `'${$('UNIQUELISTENERS').text()}'`,
averagetime: `'${$('AVERAGETIME').text()}'`,
servergenre: `'${$('SERVERGENRE').text()}'`,
serverurl: `'${$('SERVERURL').text()}'`,
songtitle: `'${$('SONGTITLE').text()}'`,
streamhits: `'${$('STREAMHITS').text()}'`,
streamuptime: `'${$('STREAMUPTIME').text()}'`
}
}).catch((err) => {
return axios.get(obj.url + '/status-json.xsl').then((json) => {
const $ = cheerio.load(json)
return {
url: obj.url + '/status-json.xsl',
genre: `'${json.data.icestats.source.genre}'`,
listeners: `'${json.data.icestats.source.listeners}'`,
server_url: `'${json.data.icestats.source.server_url}'`,
listenurl: `'${json.data.icestats.source.listenurl}'`
}
})
})
})
)
}