0

I have an array which has a list of values and some of them are promises that needs to be resolved.

allGlobalFilters": [
    {
      "id": 503,
      "pubId": 18,
      "type": 15,
      "value": "{ \"adsize\":  [\"638x335\" , \"400x300\" , \"300x1050\", \"320x100\", \"640x480\" , \"700x392\",  \"360x480\", \"896x502\", \"960x538\", \"1024x573\", \"1088x609\"]}",
      "status": 4,
      "createTs": null,
      "updateTs": null,
      "createUser": "MMM",
      "updateUser": null,
      "percentage": 100,
      "rtbSspPublishers": { // the promise part 
        "id": 18,
        "name": "Mobile Nations\r\n",
        "domain": "http://www.mobilenations.com",
        "extPublisherId": 17
      }
    },
    {
      "id": 505,
      "pubId": 19,
      "type": 15,
      "value": "{ \"adPlatformType\": [\"APP\"] }",
      "status": 4,
      "createTs": null,
      "updateTs": null,
      "createUser": null,
      "updateUser": null,
      "percentage": 0,
      "rtbSspPublishers": { // the promise part
        "id": 19,
        "name": "Tom's Guide",
        "domain": "www.tomsguide.com",
        "extPublisherId": 17
      }
    },
    {
      "id": 514,
      "pubId": 19,
      "type": 15,
      "value": "{ \"adPlatformType\": [\"WEB\"] }",
      "status": 4,
      "createTs": null,
      "updateTs": null,
      "createUser": null,
      "updateUser": null,
      "percentage": 100,
      "rtbSspPublishers": { // the promise part
        "id": 19,
        "name": "Tom's Guide",
        "domain": "www.tomsguide.com",
        "extPublisherId": 17
      }
    },
    {
      "id": 516,
      "pubId": 19,
      "type": 15,
      "value": "{\"adPlatformType\": [\"MOBILE_WEB\"]}",
      "status": 4,
      "createTs": null,
      "updateTs": null,
      "createUser": null,
      "updateUser": null,
      "percentage": 100,
      "rtbSspPublishers": { // the promise part
        "id": 19,
        "name": "Tom's Guide",
        "domain": "www.tomsguide.com",
        "extPublisherId": 17
      }
    }
  ]

Now i need to filter this array on the condition of the promise, how do I do that .

This is what i have tried.

 data.filter(d => d.rtbSspPublishers.get().then(res => res.name.includes('Mobile')));

But this does not seem to work. How to get the async value to work with the array filter?

Marek Lipka
  • 50,622
  • 7
  • 87
  • 91
INFOSYS
  • 1,465
  • 9
  • 23
  • 50
  • 2
    you can't filter synchronously on asynchronous data - you'll need to wait for the promises to resolve first, and THEN run the filter – Jaromanda X Nov 22 '17 at 05:41
  • @JaromandaX how do i wait for the same over here i know that promises are async and filters are sync . thanks can you please give some hint – INFOSYS Nov 22 '17 at 05:42
  • bluebird has something called `Promise.props` that may be what you want – Jaromanda X Nov 22 '17 at 05:44
  • This might help: https://stackoverflow.com/questions/33073509/promise-all-then-resolve, not sure though – Rajesh Nov 22 '17 at 05:44
  • that fact that your code is `rtbSspPublishers.get().then` ... suggests that `rtbSspPublishers` isn't a Promise, but some object with a `.get` method that returns a promise, which may make it a little more complex – Jaromanda X Nov 22 '17 at 05:46
  • @JaromandaX and Rajesh the thing is that the whole array is not aysnc we have a list of data but only a part of the data is async so thats whats confusing – INFOSYS Nov 22 '17 at 05:46
  • yes actually the data is coming from loopback and it is a promise but it comes like this , it a syntax of loopback the thing is that it is a object inside a object so we use get and then @JaromandaX – INFOSYS Nov 22 '17 at 06:01

2 Answers2

0

Just Map the promises to an array inside promise all, wait for them to resolve then just map them back into a new array. you can override the old array or just keep a reference to a new array.

let allGlobalFilters = [{
  "id": 503,
  "pubId": 18,
  "type": 15,
  "status": 4,
  "createTs": null,
  "updateTs": null,
  "createUser": "MMM",
  "updateUser": null,
  "percentage": 100,
  "rtbSspPublishers": Promise.resolve({
    "id": 18,
    "name": "Mobile Nations",
    "domain": "http://www.mobilenations.com",
    "extPublisherId": 17
  })
}]

Promise.all(allGlobalFilters.map(({rtbSspPublishers}) => rtbSspPublishers)).then(values => {
  const theNewValues = allGlobalFilters
                      .map((item, i) => ({...item, rtbSspPublishers: values[i]}))
                      .filter(item => item.rtbSspPublishers.name.startsWith('Mobile'))
  })

Update without object spread

Promise.all(allGlobalFilters.map(({rtbSspPublishers}) => rtbSspPublishers)).then(values => {
  const theNewValues = allGlobalFilters
                      .map((item, i) => { return  Object.assign({}, item, { rtbSspPublishers: values[i] }) })
                      .filter(item => item.rtbSspPublishers.name.startsWith('Mobile'))
    // use theNewValues right here, or call a methof
    // someMethod(theNewValues);
  })
Joey
  • 1,075
  • 8
  • 13
  • how do i filter the same array i:e allGlobalFilters with name from the promise values then ? – INFOSYS Nov 22 '17 at 06:22
  • change `const theNewValues = ` to be `allGlobalFilters = ` – Joey Nov 22 '17 at 06:24
  • @INFOSYS to opperate on `allGlobalFilters` you will have to do so in the `.then` portion of the code. if you do it before or after the `then` the array wont be updated. so make any extra calls or updates in the `then` portion – Joey Nov 22 '17 at 06:28
  • you dont have any babel presets? okay ill update it to not use the spread on objects. – Joey Nov 22 '17 at 06:31
  • if you did it correctly it should not be, i tested this on a repl and it works. you have to put the rest of your code in the `.then` part. i added some comments for where to add your code. – Joey Nov 22 '17 at 17:02
0

A more generic answer ...

Using a simple "helper" I prepared earlier

promiseProps = obj => {
    const keys = Object.keys(obj);
    return Promise.all(Object.values(obj)).then(results => Object.assign({}, ...results.map((result, index) => ({[keys[index]]: result}))));
};

You would simply

Promise.all(allGlobalFilters.map(obj => promiseProps(obj)))
.then(result => result.filter(({rtbSspPublishers}) => rtbSspPublishers.name.includes('Mobile'))
.then(filteredResult => {
    // filteredResult is your allGlobalFilters with promises resolved
    // filtered to include only the required items
    console.log(filteredResult );
});

This will work no matter how many of the (first level) properties are promises

Jaromanda X
  • 53,868
  • 5
  • 73
  • 87