skip to Main Content

I am trying to sort Shopify Blog Posts by a metafield called “Event Date.” I call on my articles.JSON but it does not come with the metafields.JSON so I then have to take that array and put it through a foreach function to attach the metafields to each article.

This is how the metafields.json for each article is setup:

{  
   "metafields":[  
      {  
         "id":5994805788772,
         "namespace":"global",
         "key":"Event-Date",
         "value":"1549256400",
         "value_type":"string",
         "description":null,
         "owner_id":15977611364,
         "created_at":"2019-02-06T18:31:44-05:00",
         "updated_at":"2019-02-06T18:31:44-05:00",
         "owner_resource":"article"
      },
      {  
         "id":5994805821540,
         "namespace":"global",
         "key":"Event-Time",
         "value":"6:00pm - 8:00pm",
         "value_type":"string",
         "description":null,
         "owner_id":15977611364,
         "created_at":"2019-02-06T18:31:45-05:00",
         "updated_at":"2019-02-06T18:31:45-05:00",
         "owner_resource":"article"
      },
      {  
         "id":6010564542564,
         "namespace":"global",
         "key":"Location",
         "value":"18th Street Location",
         "value_type":"string",
         "description":null,
         "owner_id":15977611364,
         "created_at":"2019-02-07T13:16:05-05:00",
         "updated_at":"2019-02-07T14:05:08-05:00",
         "owner_resource":"article"
      }
   ]
}

How I attach the metafields.JSON below:

var request = new XMLHttpRequest();

request.open('GET', '/admin/blogs/43130421348/articles.json');
request.responseType = 'json';
request.send();

request.onload = function() {
    var articleList = request.response; 
    var articleArray = articleList.articles;
    var date = new Date();
    var ticks = Math.floor(date.getTime() / 1000);
    var count = 0;
    articleArray.forEach(function(entry,index, object){
    var metaRequest = new XMLHttpRequest();
    metaRequest.open('GET', '/admin/blogs/43130421348/articles/'+ entry.id + '/metafields.json');
    metaRequest.responseType = 'json';
    metaRequest.send();
    console.log(index);

    metaRequest.onload = function() {
        var articleMetaObj = metaRequest.response;
        var articleMetaArr = articleMetaObj.metafields;
        entry.metafields = articleMetaArr; 
        var eventDate = entry.metafields[0].value;
   }

 });

};

I’m now trying to get rid of any article that has a date (“Key”: “Event-Date”) that has already passed compared to the current date. I’ve looked at the following Stack Overflow Post on removing objects in a foreach loop but none of its solutions prove to actually get rid of all the articles. It will get rid all of them occasionally but sometimes leave in one of the objects.

I’ve also tried an array filter but all I’ve gotten back is an empty array when I’ve used it. I’ve been stuck on this for a bit now so any help on solving it is much appreciated.

2

Answers


  1. Is your entry the article? Then you could ignore using:

    request.onload = function() {
    var articleList = request.response; 
    var articleArray = articleList.articles;
    var date = new Date();
    var ticks = Math.floor(date.getTime() / 1000);
    var count = 0;
    articleArray.forEach(function(entry,index, object){
       if(entry.'Key' !== 'Event-Date'){
            var metaRequest = new XMLHttpRequest();
            metaRequest.open('GET', '/admin/blogs/43130421348/articles/'+ entry.id + '/metafields.json');
            metaRequest.responseType = 'json';
            metaRequest.send();
            console.log(index);
    
            metaRequest.onload = function() {
            var articleMetaObj = metaRequest.response;
            var articleMetaArr = articleMetaObj.metafields;
            entry.metafields = articleMetaArr; 
            var eventDate = entry.metafields[0].value;
           }
       }
    });
    
    Login or Signup to reply.
  2. I think it would be easiest if you waited until you attached all of the metadata, and then once it is all completed, use articleArray.filter to take out the ones you don’t want. To do this, you have two options:

    Option 1 – The Old Ways (setInterval)

    Here, we keep count as the metadata is retrieved, and create an interval to check when they all have completed. Once done, a function is called (finish) that allows for continued processing.

    var request = new XMLHttpRequest();
    
    request.open('GET', '/admin/blogs/43130421348/articles.json');
    request.responseType = 'json';
    request.send();
    
    request.onload = function () {
        var articleList = request.response;
        var articleArray = articleList.articles;
        var date = new Date();
        var ticks = Math.floor(date.getTime() / 1000);
        var count = 0;  //to keep track of how many metafields have been retrieved
        var checkInterval = null;
    
        articleArray.forEach(function (entry, index) {
            var metaRequest = new XMLHttpRequest();
            metaRequest.open('GET', '/admin/blogs/43130421348/articles/' + entry.id + '/metafields.json');
            metaRequest.responseType = 'json';
            metaRequest.send();
            console.log(index);
    
            metaRequest.onload = function () {
                var articleMetaObj = metaRequest.response;
                var articleMetaArr = articleMetaObj.metafields;
                entry.metafields = articleMetaArr;
                count++;
            };
        });
    
        //Function to continue processing
        var finish = function () {
            articleArray = articleArray.filter(a => new Date(a.metafields[0].value).getTime() < date.getTime());
            //Continue on...
        };
    
        //Wait until all metafields are retrieved to continue
        checkInterval = setInterval(function () {
            if (count === articleArray.length - 1) {
                clearInterval(checkInterval);
                finish();
            }
        }, 500);
    };
    

    Option 2 – The New Razmatazz (Promises & async/await)

    Promises and async/await allow for writing some much nicer looking code when dealing with asynchronous operations.

    If you feel like using these, I would suggest digging into the documentation to get more familiar, but here is what it could look like for your task.

    //Functions that return Promises can be awaited...
    var get = url => new Promise((resolve, reject) => {
        var request = new XMLHttpRequest();
        request.open('GET', url);
        request.responseType = 'json';
        //resolve is called when successful
        request.onload = () => resolve(request.response);
        //reject is called when there's a problem
        request.onerror = err => reject(err);
        request.send();
    });
    
    //await keyword must appear in an async function
    var getArticles = async () => {
        var articleList = await get('/admin/blogs/43130421348/articles.json');
        return articleList.articles;
    };
    
    //Promise.all takes an array of promises and resolves when all of them are finished
    //This lets you skip the messy setInterval stuff
    var getArticleMetafields = async articles => {
        var requests = [];
        articles.forEach(a => {
            var url = '/admin/blogs/43130421348/articles/' + a.id + '/metafields.json';
            var promise = get(url);
            requests.push(promise);
        });
        var responses = await Promise.all(requests);
        responses.forEach((response, i) => {
            articles[i].metafields = response.metafields;
        });
        return articles;
    };
    
    //Notice the async on the handler
    document.addEventListener('DOMContentLoaded', async () => {
        var articles = await getArticles();
        articles = await getArticleMetafields(articles);
        var date = new Date();
        articles = articles.filter(a => new Date(a.metafields[0].value) < date);
        //Continue...
    });
    

    Hope this helps. Cheers!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search