Reputation: 1
I'm pretty new to JavaScript but have had some other programming experience so I'm picking most of it up (somewhat) quickly. Promises do totally confuse me.
I have a promise that took me a while to cobble together, but I finally got it working. If I call this
var test
.
.
detectActive().then(function(result) {
if (result.isActive)
{ alert("ACTIVE"); }
})
The alert pops up with the correct result. But instead of the alert, if I try to set the variable 'test' that exists outside of the promise (try to set it inside the promise, where the alert is now) it doesn't have any effect. I'm pretty sure that it is a scope issue.
// (from comments)
console.log(arguments);
detectActive().then(function(result) {
if (result.isActive) {
arguments.push("from within promise");
}
});
arguments.push("after promise");
When I try the above first console.log shows empty Array []
. arguments.push within the promise returns a log error 'TypeError: arguments.push is not a function'. But the push outside the promise works and logs Array [ "after promise", "other data in the array" ]
.
What I actually want to do is run the detectActive function and then push a value to an array that exists in the outer function. I think I need to nest another promise. I tried many different versions of this idea all produce code that doesn't run. As I said earlier it took me along time to get the single promise to work.
What is the correct way to achieve what I want?
Upvotes: 0
Views: 77
Reputation: 95654
You're right, it's a scope problem, and only because you're working with a variable named arguments
in your function. If you named it anything else it would be fine.
arguments
is a special automatically-provided variable in JavaScript, which is array-like but not an array. JavaScript automatically populates it for every function call, which helps make functions work with variable numbers of arguments.
arguments
is an array-like object, which means thatarguments
has alength
property and properties indexed from zero, but it doesn't have Array's built-in methods like forEach() or map(). However, it can be converted to a realArray
, using one ofslice()
,Array.from()
, or spread syntax.
Let's try it:
function demonstrateArguments() { // no explicit arguments
console.log(arguments.length, ": ", arguments[0], arguments[1], arguments[2]);
}
demonstrateArguments();
demonstrateArguments("a", "b");
demonstrateArguments(1, 2, 3, "no room for me");
Consequently, the function
you define within your Promise defines its own arguments
variable that doesn't have a push
function. Even if it did, it wouldn't be the same arguments
that exists outside the function.
/** Your original function, with labeled console calls. */
function originalName() {
let arguments = [];
console.log("original-before:", arguments);
detectActive().then(function(result) {
if (result.isActive) {
arguments.push("from within promise");
console.log("original-within:", arguments);
}
}).catch(console.error);
arguments.push("after promise");
console.log("original-after:", arguments);
}
/** Exactly the same, but with "values" rather than "arguments". */
function newName() {
let values = [];
console.log("new-name-before:", values);
detectActive().then(function(result) {
if (result.isActive) {
values.push("from within promise");
console.log("new-name-within:", values);
}
}).catch(console.error);
values.push("after promise");
console.log("new-name-after:", values);
}
function detectActive() {
return new Promise((res, rej) => setTimeout(res, 1000, /* argument to res = */ {isActive: true}));
}
originalName();
// delay newName call
setTimeout(newName, 3000);
Upvotes: 2