{"id":11090,"date":"2021-09-15T17:16:48","date_gmt":"2021-09-15T17:16:48","guid":{"rendered":"https:\/\/www.htmlgoodies.com\/?p=11090"},"modified":"2021-09-15T17:16:48","modified_gmt":"2021-09-15T17:16:48","slug":"rxjs-observables-withlatestfrom-zip","status":"publish","type":"post","link":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/","title":{"rendered":"Combining RxJS Observables Using the withLatestFrom and zip Operators"},"content":{"rendered":"

In Angular applications, we often rely on more than one asynchronous call to load component data. This often necessitates that we hold off on initializing the component until we have received all of the responses. One way to do that is to employ some of the RxJS library’s plethora of combination operators. In this tutorial, we’ll examine withLatestFrom<\/i> and zip<\/i>.<\/p>\n

Read:<\/strong> RxJS Observables Primer in Angular.<\/a><\/p>\n

withLatestFrom in RxJS<\/i><\/h2>\n

You could say that withLatestFrom<\/i> is the counterpart to combineLatest<\/i>. Both operators combine two or more source observables and emit values calculated from the latest values of each. What distinguishes withLatestFrom<\/i> from combineLatest<\/i> can be seen in its signature:<\/p>\n

observable.withLatestFrom(other: Observable, project: Function): Observable\r\n<\/pre>\n

As you can see, withLatestFrom<\/i> acts on a source observable to combine it with other streams to emit values calculated from the latest values of each, but only when the source emits. So, while combineLatest<\/i> emits a new value whenever there’s a new emission from any<\/strong> of the input streams, withLatestFrom<\/i> emits a new value only if there’s a new emission from the source<\/strong> stream instance.<\/p>\n

Like combineLatest<\/i>, it still waits for at least one emitted value from each stream and may complete without a single emission when the source stream completes. Moreover, it will never complete if the source stream doesn’t complete and will throw an error if any of the inner streams errors out.<\/p>\n

To better understand how withLatestFrom<\/i> works, let’s use it to calculate BMI (Body Mass Index) from two streams of weight and height values, just as we did in the combineLatest<\/i> demo<\/a>:<\/p>\n

const weight = of(70, 72, 76, 79, 75);\r\nconst height = of(1.76, 1.77, 1.78);\r\n\r\nconst bmi = weight.pipe(\r\n  withLatestFrom(height, (w, h) => {\r\n  console.log('project values: w =', w, ', h =', h);\r\n  return w \/ (h * h);\r\n}));\r\nbmi.subscribe(res => console.log('BMI is ' + res));\r\n\r\n\/\/ Output to console is:\r\nproject values: w = 70 , h = 1.78\r\nBMI is 22.093170054286073\r\nproject values: w = 72 , h = 1.78\r\nBMI is 22.724403484408533\r\nproject values: w = 76 , h = 1.78\r\nBMI is 23.98687034465345\r\nproject values: w = 79 , h = 1.78\r\nBMI is 24.933720489837143\r\nproject values: w = 75 , h = 1.78\r\nBMI is 23.671253629592222\r\n<\/pre>\n

In the above example, the weight<\/i> observable provides the source stream. As such, withLatestFrom<\/i> calculated the BMI whenever it emits a value. In each case, th final value height<\/i> value of 1.78 is utilized.<\/p>\n

Compare that output to what was produced by combineLatest<\/i>:<\/p>\n

\/\/ Output to console is:\r\n\/\/ project values: w = 75, h = 1.76\r\n\/\/ BMI is 24.212293388429753\r\n\/\/ project values: w = 75, h = 1.77\r\n\/\/ BMI is 23.93948099205209\r\n\/\/ project values: w = 75, h = 1.78\r\n\/\/ BMI is 23.671253629592222\r\n<\/pre>\n

It only emitted three BMI values – one of each input stream emission combinations. In this case, the number of values emitted from combineLatest<\/i> was determined by the stream that emitted the least number of values, which was height<\/i>.<\/p>\n

zip in RxJS<\/i><\/h2>\n

Typically, an operator’s name reveals enough about its functioning to remind us what it does, once you’ve familiarized yourself with it. In the case of zip<\/i>, we have an operator that combines observable streams in a way that mimics the behavior of a zipper on clothing or a bag. As such, it combines two or more stream sequences as an array of values whose length is equal to the number of input streams provided, i.e., a pair in case of two input streams. To do that, zip<\/i> waits for values to be emitted from all input streams, then emits them as an array.<\/p>\n

It is also worth noting that zip<\/i> will only emit an array once it has fresh values from each source sequence. So if one of the source observables emits values faster than the others, the rate of publishing will be dictated by the slowest stream.<\/p>\n

Zip<\/i> stops emitting values when any of the input streams complete and the corresponding new values are emitted from other streams. Conversely, it will never complete if none of the input streams completes and will throw an error if any of the inner streams errors out.<\/p>\n

Here is zip<\/i>‘s signature:<\/p>\n

zip(observable_1<\/i>[, observable_2<\/i>...observable_n<\/i>]): Observable\r\n<\/pre>\n

The following code shows the zip<\/i> operator in action:<\/p>\n

import { map } from 'rxjs\/operators';\r\nimport { of, zip } from 'rxjs';\r\n\r\nlet age$ = of<number>(30, 29, 44);\r\nlet name$ = of<string>('Bob', 'Carol', 'Jim');\r\nlet isDev$ = of<boolean>(true, true, false, false);\r\n\r\nzip(age$, name$, isDev$)\r\n  .pipe(map(([age, name, isDev]) => ({ age, name, isDev })))\r\n  .subscribe(res => console.log(res));\r\n\r\n\/\/ outputs\r\n\/\/ { age: 30, name: 'Bob', isDev: true }\r\n\/\/ { age: 29, name: 'Carol', isDev: true }\r\n\/\/ { age: 44, name: 'Jim', isDev: false }\r\n<\/pre>\n

In the above snippet, three streams that emit all of there values without any delay. The zip<\/i> output is piped to the RxJS map<\/i> operator so that input parameters are displayed as name: value<\/i> pairs in the subscribe function. Notice that the last boolean value of false<\/i> is never emitted because the other two streams have completed by that point.<\/p>\n

A zip<\/i> Example with Delay<\/h3>\n

As this second example shows, introducing a delay to stream emissions does not change the results:<\/p>\n

zip(\r\n  age$.pipe(delay(2000)), \r\n  name$.pipe(delay(1000)),  \r\n  isDev$.pipe(delay(3000))\r\n)\r\n  .pipe(map(([age, name, isDev]) => ({ age, name, isDev })))\r\n  .subscribe(res => console.log(res));\r\n  \r\n\/\/ outputs\r\n\/\/ { age: 30, name: 'Bob', isDev: true }\r\n\/\/ { age: 29, name: 'Carol', isDev: true }\r\n\/\/ { age: 44, name: 'Jim', isDev: false }\r\n<\/pre>\n

The only difference is that zip<\/i> won’t emit anything until it has received values from each of the input streams, meaning that the subscribe function won’t receive a value until the isDev$<\/i> observable emits after a delay of 3 seconds. All values are subsequently emitted in quick succession.<\/p>\n

RxJS Combination Operators<\/h2>\n

In this tutorial, we learned how to use two of the RxJS library’s two most powerful combination operators: withLatestFrom<\/i> and zip<\/i>.<\/p>\n

All of the above code snippets are included in the stackblitz.com demo<\/a> so that you can play with the code and observe the results.<\/p>\n","protected":false},"excerpt":{"rendered":"

In Angular applications, we often rely on more than one asynchronous call to load component data. This often necessitates that we hold off on initializing the component until we have received all of the responses. One way to do that is to employ some of the RxJS library’s plethora of combination operators. In this tutorial, […]<\/p>\n","protected":false},"author":90,"featured_media":11067,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[30620],"tags":[3385,33896,30872],"b2b_audience":[37],"b2b_industry":[65],"b2b_product":[76,131,133,107,94,99,80,128,98],"acf":[],"yoast_head":"\nRxJS Observables: withLatestFrom and zip | HTMLGoodies.com<\/title>\n<meta name=\"description\" content=\"In Angular applications, we often rely on more than one asynchronous call to load component data. Learn how to use RxJS Observables.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"RxJS Observables: withLatestFrom and zip | HTMLGoodies.com\" \/>\n<meta property=\"og:description\" content=\"In Angular applications, we often rely on more than one asynchronous call to load component data. Learn how to use RxJS Observables.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/\" \/>\n<meta property=\"og:site_name\" content=\"HTML Goodies\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-15T17:16:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1080\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@htmlgoodies\" \/>\n<meta name=\"twitter:site\" content=\"@htmlgoodies\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Rob Gravelle\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#organization\",\"name\":\"HTML Goodies\",\"url\":\"https:\/\/www.htmlgoodies.com\/\",\"sameAs\":[\"https:\/\/twitter.com\/htmlgoodies\"],\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png\",\"contentUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png\",\"width\":584,\"height\":136,\"caption\":\"HTML Goodies\"},\"image\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#website\",\"url\":\"https:\/\/www.htmlgoodies.com\/\",\"name\":\"HTML Goodies\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.htmlgoodies.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#primaryimage\",\"url\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png\",\"contentUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png\",\"width\":1080,\"height\":720,\"caption\":\"RxJS Angular Tutorials\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#webpage\",\"url\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/\",\"name\":\"RxJS Observables: withLatestFrom and zip | HTMLGoodies.com\",\"isPartOf\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#primaryimage\"},\"datePublished\":\"2021-09-15T17:16:48+00:00\",\"dateModified\":\"2021-09-15T17:16:48+00:00\",\"description\":\"In Angular applications, we often rely on more than one asynchronous call to load component data. Learn how to use RxJS Observables.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.htmlgoodies.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Combining RxJS Observables Using the withLatestFrom and zip Operators\"}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75\"},\"headline\":\"Combining RxJS Observables Using the withLatestFrom and zip Operators\",\"datePublished\":\"2021-09-15T17:16:48+00:00\",\"dateModified\":\"2021-09-15T17:16:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#webpage\"},\"wordCount\":733,\"publisher\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png\",\"keywords\":[\"JavaScript\",\"Observables\",\"RxJS\"],\"articleSection\":[\"Javascript\"],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75\",\"name\":\"Rob Gravelle\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg\",\"contentUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg\",\"caption\":\"Rob Gravelle\"},\"description\":\"Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.\",\"url\":\"https:\/\/www.htmlgoodies.com\/author\/rob-gravelle\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"RxJS Observables: withLatestFrom and zip | HTMLGoodies.com","description":"In Angular applications, we often rely on more than one asynchronous call to load component data. Learn how to use RxJS Observables.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/","og_locale":"en_US","og_type":"article","og_title":"RxJS Observables: withLatestFrom and zip | HTMLGoodies.com","og_description":"In Angular applications, we often rely on more than one asynchronous call to load component data. Learn how to use RxJS Observables.","og_url":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/","og_site_name":"HTML Goodies","article_published_time":"2021-09-15T17:16:48+00:00","og_image":[{"width":1080,"height":720,"url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_creator":"@htmlgoodies","twitter_site":"@htmlgoodies","twitter_misc":{"Written by":"Rob Gravelle","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Organization","@id":"https:\/\/www.htmlgoodies.com\/#organization","name":"HTML Goodies","url":"https:\/\/www.htmlgoodies.com\/","sameAs":["https:\/\/twitter.com\/htmlgoodies"],"logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png","contentUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png","width":584,"height":136,"caption":"HTML Goodies"},"image":{"@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/"}},{"@type":"WebSite","@id":"https:\/\/www.htmlgoodies.com\/#website","url":"https:\/\/www.htmlgoodies.com\/","name":"HTML Goodies","description":"","publisher":{"@id":"https:\/\/www.htmlgoodies.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.htmlgoodies.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#primaryimage","url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png","contentUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png","width":1080,"height":720,"caption":"RxJS Angular Tutorials"},{"@type":"WebPage","@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#webpage","url":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/","name":"RxJS Observables: withLatestFrom and zip | HTMLGoodies.com","isPartOf":{"@id":"https:\/\/www.htmlgoodies.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#primaryimage"},"datePublished":"2021-09-15T17:16:48+00:00","dateModified":"2021-09-15T17:16:48+00:00","description":"In Angular applications, we often rely on more than one asynchronous call to load component data. Learn how to use RxJS Observables.","breadcrumb":{"@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.htmlgoodies.com\/"},{"@type":"ListItem","position":2,"name":"Combining RxJS Observables Using the withLatestFrom and zip Operators"}]},{"@type":"Article","@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#article","isPartOf":{"@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#webpage"},"author":{"@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75"},"headline":"Combining RxJS Observables Using the withLatestFrom and zip Operators","datePublished":"2021-09-15T17:16:48+00:00","dateModified":"2021-09-15T17:16:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#webpage"},"wordCount":733,"publisher":{"@id":"https:\/\/www.htmlgoodies.com\/#organization"},"image":{"@id":"https:\/\/www.htmlgoodies.com\/javascript\/rxjs-observables-withlatestfrom-zip\/#primaryimage"},"thumbnailUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/09\/RxJS-tutorials.png","keywords":["JavaScript","Observables","RxJS"],"articleSection":["Javascript"],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75","name":"Rob Gravelle","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/image\/","url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg","contentUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg","caption":"Rob Gravelle"},"description":"Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.","url":"https:\/\/www.htmlgoodies.com\/author\/rob-gravelle\/"}]}},"_links":{"self":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/posts\/11090"}],"collection":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/users\/90"}],"replies":[{"embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/comments?post=11090"}],"version-history":[{"count":0,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/posts\/11090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/media\/11067"}],"wp:attachment":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/media?parent=11090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/categories?post=11090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/tags?post=11090"},{"taxonomy":"b2b_audience","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/b2b_audience?post=11090"},{"taxonomy":"b2b_industry","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/b2b_industry?post=11090"},{"taxonomy":"b2b_product","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/b2b_product?post=11090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}