make promise chaining more sustainable

This commit is contained in:
fenwick67 2019-08-02 11:10:45 -04:00
parent 49f6a0b8e2
commit 9d85c029f4
1 changed files with 37 additions and 20 deletions

View File

@ -3,16 +3,25 @@ var fs = require('fs');
var template = ejs.compile(fs.readFileSync('./lib/template.ejs', 'utf8')); var template = ejs.compile(fs.readFileSync('./lib/template.ejs', 'utf8'));
var timeAgo = require('timeago.js'); var timeAgo = require('timeago.js');
// TODO try https://www.npmjs.com/package/request-promise-cache for the requests
var request = require('request-promise-cache') var request = require('request-promise-cache')
const hour = 3600000; const hour = 3600000;
// get JSON for an AP URL // get JSON for an AP URL, by either fetching it or grabbing it from a cache.
// TODO make it reject on HTTP 4xx or 5xx
// Honestly request-promise-cache should be good enough. Redis would be a nice upgrade but for
// a single process install it will be fine.
// note: rejects on HTTP 4xx or 5xx
async function apGet(url,ttl) { async function apGet(url,ttl) {
return new Promise(function(resolve,reject){ return new Promise(function(resolve,reject){
// fail early
if (!url){
reject(new Error('URL is invalid'));
}
request( { request( {
uri:url, uri:url,
cacheKey:url, cacheKey:url,
@ -29,13 +38,24 @@ async function apGet(url,ttl) {
} }
// never rejects, instead it returns an object with a status, error and/or result. // like Promise.all except returns null on error instead of failing all the promises
async function apGetNoReject(...args){ async function promiseSome(proms){
return new Promise(function(resolve,reject){
apGet(...args) function noRejectWrap(prom){
.then(res=>resolve({status:true,result:res})) return new Promise(function(resolve,reject){
.catch(e=>resolve({status:false,error:e}))
}); prom // it's already been called
.then(resolve)
.catch(e=>{
// console.warn(e);// for debugging
resolve(null)
})
})
}
return await Promise.all(proms.map(noRejectWrap))
} }
module.exports = async function (opts) { module.exports = async function (opts) {
@ -97,16 +117,15 @@ async function itemsForFeed(opts,user,feed) {
var boostData = []; var boostData = [];
var boostUrls = feed.orderedItems.filter(i=>i.type=="Announce").map(i=>i.object); var boostUrls = feed.orderedItems.filter(i=>i.type=="Announce").map(i=>i.object);
// console.log(boostUrls); // console.log(boostUrls);
boostData = await Promise.all(boostUrls.map(apGetNoReject)); boostData = await promiseSome(boostUrls.map(apGet));
boostData = boostData.map(d=>d.result||{});
// now get user data for each of those // now get user data for each of those
let userData = await Promise.all(boostData.map(d=>d.attributedTo||'').map(apGetNoReject)); let userData = await promiseSome(boostData.map(d=>d?d.attributedTo||'':null).map(apGet));
// put a ._userdata key on the item object if this is a boost etc // put a ._userdata key on the item object if this is a boost
for (var i = 0; i < boostData.length; i ++){ for (var i = 0; i < boostData.length; i ++){
if (userData[i].status){ if (userData[i] && boostData[i]){
boostData[i]._userdata = userData[i].result; boostData[i]._userdata = userData[i];
} }
} }
@ -116,8 +135,8 @@ async function itemsForFeed(opts,user,feed) {
boostData.forEach((boostToot)=>{ boostData.forEach((boostToot)=>{
if (!boostToot.id){ if (!boostToot){// failed request
return;// case where it's a {} b/c the request failed or w/e return;
} }
// inject in-place into items // inject in-place into items
@ -142,8 +161,6 @@ async function itemsForFeed(opts,user,feed) {
return items.filter((item)=>{ return items.filter((item)=>{
// this is temporary, don't handle boosts (TODO)
// return item.type == "Create" && item.object && item.object.type=="Note";
return typeof item.object == 'object';// handle weird cases return typeof item.object == 'object';// handle weird cases
}).map((item)=>{ }).map((item)=>{