在尝试学习如何使用JavaScript Promises时,我尝试实现一个允许将XHR的结果分配给变量的函数。我知道这可能不是解决这个问题的惯用方法。不过,如果我遇到令人费解的问题,这是一个有趣的问题。
我们的想法是将XHR包装在Promise中,并传递一个resolve函数,该函数将XHR响应分配给变量。以下是一些代码和解释。在控制台中测试它的一切都在这里:
function getJSON(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("get", url);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status < 400) {
resolve(xhr.responseText);
}
};
xhr.send();
});
}
function assignDataTo(target, url, ctx) {
// Asynchronously assign JSON response to `target` variable
getJSON(url)
.then(function(data) {
ctx.target = JSON.parse(data);
}, function(error) {
console.log(error);
}
);
}
var targetVariable,
url = "https://data.baltimorecity.gov/resource/n4ma-fj3m.json?$select=*&$limit=5";
assignDataTo(targetVariable, url, window);
valueOf(targetVariable); // Error: undefined
valueOf(window.target); // JSON: xhr.response
将上下文参数添加到assignDataTo
是为了更加具体地了解接收数据的变量的范围。我发现ctx.target
(或ctx[target]
)评估为window.target
,而不是像我希望的那样替换函数参数(即ctx.target == window.targetVariable
)。
如何将指向实际变量的指针作为assignDataTo
函数的参数传递给我? (其次,欢迎任何关于这种使用承诺的一般策略的评论。)
答案 0 :(得分:2)
字符串,布尔值和数字在javascript中按值传递。但是,您可以将targetVariable
包装在一个将通过引用传递的对象中。
ctx.target = JSON.parse(data);
实际上只为target
对象中的键ctx
设置了一个值,在您的情况下它将是window
对象。它与您作为参数传递给函数的参数target
无关。
此外,assignDataTo()
函数异步运行,因此调用valueOf(targetVariable)
不起作用,因为Promise可能还没有解决,即。 XHR的结果尚未到来。更好的解决方案就是这样。
function assignDataTo(url) {
// Return a Promise
return getJSON(url)
.then(function(data) {
//resolve the Promise with this value
return JSON.parse(data);
}, function(error) {
console.log(error);
}
);
}
var targetVariable;
//wait for the Promise to be resolved and then assign the variable and do whatever with it
assignDataTo(url).then(function(result) {
targetVariable = result;
valueOf(targetVariable);
});
答案 1 :(得分:0)
JavaScript没有像其他语言那样显式引用(或指针)(例如:PHP&amp; $ variable),但在使用对象时它使用引用。
当向函数发送数组(也是JavaScript中的对象)时,它将获得相同的数组引用。这就是为什么在函数内部进行任何更改的原因将在外面提供。
示例:
function addEl(arr) {
arr.push(3);
}
var ourArray = [1, 2]; // [1, 2]
addEl(ourArray);
console.log(ourArray); // [1, 2, 3]
这适用于Objects,但它与原始类型有所不同:string,number或boolean。 在向函数发送基元时,它会创建一个基元的副本,因此它不会从函数外部更改基元。
原语示例:
function increment(el) {
el += 1;
}
var numb = 1;
increment(numb);
console.log(numb); // 1
代码中的内容相同:
targetVariable
是一个原始变量
window
是一个对象。
写作时:
ctx.target
你实际上是在ctx中添加一个新参数(对窗口的引用)。如果您想更改&#39; targetVariable&#39;,请在您的函数中将JSON.parse(数据)分配给window.targetVariable:
function assignDataTo(url, ctx) {
// Asynchronously assign JSON response to `target` variable
getJSON(url)
.then(function(data) {
ctx.targetVariable = JSON.parse(data);
}, function(error) {
console.log(error);
}
);
}
// ...
assignDataTo(url, window);