filmplane filmplane - 6 months ago 70
Node.js Question

How to avoid async.waterfall "TypeError: Cannot read property of undefined"?

I am working on an async.waterfall that I am unsure of how to avoid: "TypeError: Cannot read property 'MediaUrl' of undefined". This TypeError doesn't occur each time the script is run.

The flow is as follows:


  1. getName (randomly chooses a name from a list of names

  2. searchImage (uses the Bing search API to search photographs associated with that name

  3. processBotdata (takes the results from Bing and randomly chooses one of the search results)



Step 3 is where the issue occurs:

function processBotdata (searchData, callback) {

var photographer = searchData.photographer // the search name
var array = searchData.array; // search results from bing
var randomIndex = Math.floor(Math.random() * array.length);
var mediaUrl = array[randomIndex].MediaUrl; // TypeError here!
var sourceUrl = array[randomIndex].SourceUrl;
var searchData = {
photographer,
mediaUrl,
sourceUrl
};
fs.readFile('results.json', function (err, data) {
var json = JSON.parse(data);
json.push(['search results for ' + photographer + ': ',
'mediaUrl: ' + searchData.mediaUrl,
'sourceUrl: ' + searchData.sourceUrl]);

fs.writeFile("results.json", JSON.stringify(json, null, "\t"));
console.log(' ==========> searchData appended to results.json file...')
});
console.log(' ==========> searchData has now been processed for upcoming tweet...');
setTimeout(function() {
callback(null, searchData);
console.log(searchData);
}, 5000);
}


I implemented a
setTimeout
for this function hoping that would resolve the issue. My thinking was that the Bing results
searchData.array
was not yet available to be processed, i.e. randomized and selected in this function. As I am new to Node.js and JavaScript I am unsure of my programming error here. I saw this post and I am wondering if it is related to the Bing Search Array which returns the top 50 results.

Update: here is how the
async.waterfall
is called:

async.waterfall([
getName,
async.retryable([opts = {times: 5, interval: 500}], searchImage),
async.retryable([opts = {times: 3, interval: 1000}], processBotdata),
async.retryable([opts = {times: 3, interval: 500}], getImage)
],
function(error, result) {
if (error) {
console.error(error);
return;
}
});


UPDATE:

Based on troubleshooting procedures suggested in the answer provided, I was able to determine the TypeError was a result of the
randomIndex
returning
0
. Updated variable as follows to resolve the issue:
var randomIndex = Math.floor((Math.random() * array.length)+1);

Answer

The most obvious possibility is that there is no object at the array index that you're getting. Since you're going after a random index, it makes sense that some random numbers are hitting populated indices, others are not. Is there any chance that the array is sparse or that the random number you're generating is out of range despite your attempts with Math.floor?

I'd check first in any case, something like:

var obj = array[randomIndex];
if(obj){
 // do your stuff
}
Comments