I’m attempting to replace url’s in a string by calling a function that shortens the url’s and then replaces the text. The shortening logic works perfectly, and I end up with the proper replacement url, however i cannot get the replace function to work correctly. Here is my code.
var newtext = shortenUrl(curText);
var shortenUrl = function (text) {
var exp = /(ftp|http|https):\/\/(?!bit\.ly)(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ig;
text.replace(exp,
function ($1) {
$.getJSON("http://api.bitly.com/v3/shorten?login=xxxxxx&apiKey=xxxx&longUrl=" + escape($1) + "&format=json",
function (result) {
return result.data.url;
});
});
return text;
};
result.data.url contains a proper shortened url per the bit.ly API specs; however,
newtext is always null for some reason.
text.Replace will not change the contents of text => you need to say text = text.Replace(…) because strings in javascript are immutable (https://stackoverflow.com/q/51193/4572 for more info)
getJSON is performed asynchronously meaning that execution of the function that you feed to replace will start the JSON call but doesn’t wait for the JSON call to finish , you need to use $.ajax instead with the async option turned off (see the code below, as well as this link: Is it possible to set async:false to $.getJSON call)
Because the JSON call merely executes a callback (ie function(result)) it doesn’t actually return a value so you need to create what is called a “closure” in order to get state (result.data.url) from inside your function(result) call to the parent scope (in this case the scope created by function($1)). Closures can get very confusing, especially in javascript, sometimes yielding non-obvious results. Thankfully this is a simple closure. For a little more info you can checkout this https://stackoverflow.com/q/7363168/4572, or the google.
Here is the code that works correctly for me: