Having a little trouble with skipping a callbacks returns. Here is the question:
Write a function, tap, which accepts an array, items, and a callback function, cb. The callback function should be invoked on the array and then the returned value should be the array regardless of what the callback returns.
My Attempt:
function tap(items, cb){
let result = items.map(cb)
return result;
}
Samples:
console.log(tap([1, 2, 3], function (items) {
items.pop();
})).reverse(); // [2,1]
console.log(tap(["a", "b", "c"], function (items) {
return items[0];
})); // ["a","b","c"]
When I put in this code, I'm hoping it will map the callback functions to the items array.
I received the following for each test case:
a. TypeError: items.pop is not a function
b. [ 'a', 'b', 'c' ]
The instructions don't say anyting about mapping the function, you're just supposed to invoke it on the array as a whole.
Since you're supposed to return the original array, you don't need to assign the callback result to a variable. Just return items.
You also need to call reverse() on the result returned by tap(). You're calling it on the result of console.log(), but it doesn't return anything.
function tap(items, cb){
cb(items);
return items;
}
console.log(tap([1, 2, 3], function (items) {
items.pop();
}).reverse()); // [2,1]
console.log(tap(["a", "b", "c"], function (items) {
return items[0];
})); // ["a","b","c"]
Related
I wrote the code to iterate through a given array and then invoke the function subtractTwo on each element. However, when I run the function map the array argument returns unchanged. Does anyone know why this might be?
// create the subtractTwo function, callback function
function subtractTwo (number) {
return number - 2;
}
// create higher-order function, map
function map (array, callback) {
// initiate a for loop, looping through the array and invoking the callback on each element;
for (let i = 0; i < array.length; i ++) {
callback(array[i]);
}
//return the new array
return array;
}
//console.log(subtractTwo(4));
// Uncomment these to check your work!
console.log(typeof subtractTwo); // should log: 'function'
console.log(typeof map); // should log: 'function'
console.log(map([3,4,5], subtractTwo)); // should log: [ 1, 2, 3 ]```
I have an array of functions. Then I use forEach loop to pass the argument to these functions. Although when I try to call first function I get undefined in the console instead of 'hey'
Then I try to make a new array from the old one. And try to use map to get the array of functions with the argument passed into each one, but I get an array of three undefined items instead, so I can't even call a function.
const arr = [(arg) => {console.log(arg)}, (arg) => {}, (arg) => {} ];
arr.forEach(func => func('hey'));
arr[0]();
const arr2 = arr.map(func => func('ho'));
console.log(arr2);
arr2[0]();
What's the matter in both cases?
There's no problem in the first case, though arr[0](); will just print undefined because you've passed no argument.
In the second case, the resulting array contains the result of the invocation of each function, each of which returns undefined, so there are no functions in arr2 to invoke.
Your code snippet had the JS in the HTML section, so it didn't run at all.
const arr = [(arg) => { console.log(arg) }, (arg) => {}, (arg) => {}];
arr.forEach(func => func('hey'));
arr[0](); // <-- You're passing no argument here
// This invokes the functions, and builds an array of the functions'
// return values, all of which are `undefined`.
const arr2 = arr.map(func => func('ho'));
console.log(arr2);
arr2[0]();
I am attempting to return a new array, created by combining arrays from several get requests. The new array returns correctly within the async.eachSeries async library function, however the parent function returns undefined.
My understanding is that the return within the parent function is running synchronously with the async.eachSeries() (before it can finish), which causes the parent function to return undefined.
var array_strings = [ “someUrl”, “someUrl”, “someUrl” ]
function get_forEachUrlString(base_url, array_strings) {
…
var combinedArray = [];
var mergedArray = [];
…
async.eachSeries(array_strings, function(item, done) {
…
$.get(bas_url+item, function(data) {
…
combinedArray.push(data)
done(); // stopping the async looping
mergedArray = [].concat.apply([], combinedArray); // Merging the array of combined arrays
});
}, function(err) {
if (err) {
throw err;
}
console.log("All requests are done");
console.log(mergedArray); // logs correct array
return mergedArray
});
console.log(mergedArray); // logs [] empty array
return mergedArray // Hoping this would return the newly created mergedArray
}
get_forEachUrlString(“someBaseUrl”, array_strings) // Attempting to return mergedArray
// this function tries to call the mergedArray, but returns undefined
function initialRender() {
…
console.log(merged) // returns undefined
}
I have been searching for a way to get the parent function get_forEachUrlString() to return the value produced by the async.eachSeries function. I believe I will need to run a callback, but after trying several different combinations I’m still stumped.
How can I get the new array I’ve created, mergedArray to return from the function get_forEachUrlString()?
EDIT: I failed to mention that I am attempting to call the returned value from get_forEachUrlString() within initialRender(). See how I fixed this in my answer below.
After some trial and error I was able to get this working. I was attempting to place any number of callbacks, but what I really needed to do was place the initialRender() function within the get_forEachUrlString() function and pass the new mergedArray value to the initialRender() function.
So the proper setup looks like this.
function get_forEachUrlString(base_url, array_strings) {
…
async.eachSeries(array_strings, function(item, done) {
…
}, function(err) {
…
mergedArray = [].concat.apply([], combinedArray);
initialRender(mergedArray);
});
}
get_forEachUrlString(“someBaseUrl”, array_strings)
Then the initialRender() returns what it should.
In a functional programming exercise I found online, the instructions are as follows:
"Implement JavaScript’s native ‘filter’ method that takes two arguments (a collection and a test function that returns either a ‘true’ or a ‘false’) and iterates over the collection using the ‘each’ function you wrote earlier and returns the resultant array."
I've already completed the first part of the exercise and created a function that implements JS' forEach method:
var each = function(collection, iterator) {
if(Array.isArray(collection)){
for(var i = 0; i < collection.length; i++){
// value, key/property, collection
iterator(collection[i],i,collection);
}
} else if (typeof collection === "object"){
for(var property in collection){
iterator(collection[property], property, collection);
}
}else{
console.log("you messed up!");
}
};
Test my function with:
function returnOdds(currentEl) {
return currentEl % 2 !== 0;
}
console.log(filter([1, 2, 3], returnOdds)); // output: 1, 3
I'm not sure how to call my 'each' function on the 'collection' parameter inside my filter function.
Is this legal to do?
function filter(collection, test) {
each(collection);
}
Or perhaps I can call the 'test' parameter as a function that checks to see if collection[i] is not an even/odd number?
function filter(collection, test) {
var odd = function(each()){
each(collection){
if(collection[i] !== 0){
return odd;
}
}
}
}
I am wondering if any of this even makes sense or can be done.
The filter() function that you are being asked to implement needs to somehow build up a new array of values that pass the test, and then return that new array. Here's one way to do it that uses your existing each() method:
var filter = function(collection, test) {
var results = [];
each(collection, function(val) {
if (test(val)) {
results.push(val);
}
});
return results;
};
You can then call this function in the way you showed in the middle of your question, passing in an array and a reference to some other function that will return true or false for a given item:
var oddNumbers = filter([1, 2, 3], returnOdds);
Demo: https://jsfiddle.net/4rj7phot/
So this works as follows:
Create an empty array for the results.
Use your each() function to execute an anonymous function for each item in the collection argument.
Within the anonymous function, call the function provided in the test argument, passing the current item value, and if that function returns true (or a truthy value) add the item to the results array.
Return the results.
I'll leave any validation of the arguments (e.g., checking that test actually is a function) to you.
Say I have an array and a function A:
var array = ['a', 'b', 'c'];
function A(p) { ... };
now I want to pass each item of array to function A, and want them to be executed in a sequential order. usually there won't be any problem. I can do:
array.forEach(function(item) {
A(item);
}
however, if there are some asynchronous action in A, everything becomes messed up. so the question is:
How can I have them executed orderly even if there are asynchronous actions in A?
By which I mean, I want A('b') to be executed after A('a') is completely finished (including all the asynchronous actions in there).
I guess there must have been some utilities doing such things already. can someone shed me some light?
This is a perfect use case for "eachSeries" from async.js
You could use it this way
async.eachSeries(array, A, function(err) {
// this function gets called at the end
// after your array has been looped
});
And you would have to modify your A function with a second parameter - a callback.
function A(p, callback) {
// ...
return callback();
}
That calls the callback parameter once your async calls in A are finished.
JavaScript Promises allow you to do just that.
This example is pretty convoluted, but it shows some aspects of using Promises:
var arr = ['a', 'b', 'c'];
function processAsync(val) {
return new Promise(function(res, rej) {
console.log("Starting:", val);
setTimeout(function () {
console.log("Done:", val);
res();
}, 1000);
});
}
arr.reduce(function(promise, i) {
return promise.then(processAsync.bind(null, i));
}, Promise.resolve());
var array = ['a', 'b', 'c'],i = 0;
var A = function(p){
//some code
$.ajax({
success:function(){
try{
A(item[++i]);
}catch{
return;
}
}
});
}
Are you mean to this?