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 timeAgo = require('timeago.js');
// TODO try https://www.npmjs.com/package/request-promise-cache for the requests
var request = require('request-promise-cache')
const hour = 3600000;
// get JSON for an AP URL
// TODO make it reject on HTTP 4xx or 5xx
// get JSON for an AP URL, by either fetching it or grabbing it from a cache.
// 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) {
return new Promise(function(resolve,reject){
// fail early
if (!url){
reject(new Error('URL is invalid'));
}
request( {
uri: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.
async function apGetNoReject(...args){
return new Promise(function(resolve,reject){
apGet(...args)
.then(res=>resolve({status:true,result:res}))
.catch(e=>resolve({status:false,error:e}))
});
// like Promise.all except returns null on error instead of failing all the promises
async function promiseSome(proms){
function noRejectWrap(prom){
return new Promise(function(resolve,reject){
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) {
@ -97,16 +117,15 @@ async function itemsForFeed(opts,user,feed) {
var boostData = [];
var boostUrls = feed.orderedItems.filter(i=>i.type=="Announce").map(i=>i.object);
// console.log(boostUrls);
boostData = await Promise.all(boostUrls.map(apGetNoReject));
boostData = boostData.map(d=>d.result||{});
boostData = await promiseSome(boostUrls.map(apGet));
// 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 ++){
if (userData[i].status){
boostData[i]._userdata = userData[i].result;
if (userData[i] && boostData[i]){
boostData[i]._userdata = userData[i];
}
}
@ -116,8 +135,8 @@ async function itemsForFeed(opts,user,feed) {
boostData.forEach((boostToot)=>{
if (!boostToot.id){
return;// case where it's a {} b/c the request failed or w/e
if (!boostToot){// failed request
return;
}
// inject in-place into items
@ -142,8 +161,6 @@ async function itemsForFeed(opts,user,feed) {
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
}).map((item)=>{