我如何从函数 foo 返回一个无同步请求的答案/结果?
我正在尝试从呼叫返回的值,以及将结果分配到函数内部的本地变量,并返回其中一个,但没有这些方式实际上返回答案 - 他们都返回不确定的或无论变量结果的初始值是什么。
一个不同步函数的例子,接受召回(使用 jQuery 的 ajax 函数):
function foo() {
var result;
$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});
return result; // It always returns `undefined`
}
使用 Node.js 的例子:
function foo() {
var result;
fs.readFile("path/to/file", function(err, data) {
result = data;
// return data; // <- I tried that one as well
});
return result; // It always returns `undefined`
}
例如,使用那时承诺的区块:
function foo() {
var result;
fetch(url).then(function(response) {
result = response;
// return response; // <- I tried that one as well
});
return result; // It always returns `undefined`
}
您可以使用此自定义图书馆(使用 Promise 编写)进行远程通话。
function $http(apiConfig) {
return new Promise(function (resolve, reject) {
var client = new XMLHttpRequest();
client.open(apiConfig.method, apiConfig.url);
client.send();
client.onload = function () {
if (this.status >= 200 && this.status < 300) {
// Performs the function "resolve" when this.status is equal to 2xx.
// Your logic here.
resolve(this.response);
}
else {
// Performs the function "reject" when this.status is different than 2xx.
reject(this.statusText);
}
};
client.onerror = function () {
reject(this.statusText);
};
});
}
简单的使用例子:
$http({
method: 'get',
url: 'google.com'
}).then(function(response) {
console.log(response);
}, function(error) {
console.log(error)
});
如果您不使用 jQuery 在您的代码中,这个答案是为您
function foo() {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', "/echo/json");
httpRequest.send();
return httpRequest.responseText;
}
var result = foo(); // Always ends up being 'undefined'
(注意,对于使用新的Fetch API、Angular 或承诺的人,我在下面添加了另一个答案)
你所面临的
这里有一个简单的模拟:
function getFive(){
var a;
setTimeout(function(){
a=5;
},10);
return a;
}
(重定向)
function onComplete(a){ // When the code completes, do this
alert(a);
}
function getFive(whenDone){
var a;
setTimeout(function(){
a=5;
whenDone(a);
},10);
}
使用将是:
getFive(onComplete);
同步AJAX - 不要这样做!!!
var request = new XMLHttpRequest();
request.open('GET', 'yourURL', false); // `false` makes the request synchronous
request.send(null);
if (request.status === 200) {// That's HTTP for 'ok'
console.log(request.responseText);
}
二、修复代码
如:
var result = foo();
// Code that depends on `result` goes here
变成:
foo(function(result) {
// Code that depends on `result`
});
function myHandler(result) {
// Code that depends on `result`
}
foo(myHandler);
function foo(callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.onload = function(){ // When the request is loaded
callback(httpRequest.responseText);// We're calling our method
};
httpRequest.open('GET', "/echo/json");
httpRequest.send();
}
我们现在已经使我们的 foo 函数接受一个行动运行,当 AJAX 成功完成时,我们可以通过检查答案状态是否不为 200 进行进一步扩展,并按照此进行操作(创建一个错误处理器等)。
如果你仍然很难理解这一点,请阅读MDN的AJAX开始指南。
var milk = order_milk();
put_in_coffee(milk);
这个问题的经典JavaScript方法,利用JavaScript支持作为可以通过的第一类对象的功能,是将一个功能作为一个参数转移到无同步的请求,它将随后引用,当它在未来完成任务时。
order_milk(put_in_coffee);
order_milk kicks off, orders the milk, then, when and only when it arrives, it invokes put_in_coffee。
order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }
我正在转到把牛奶放进去,以及当牛奶放进去后执行的行动(喝咖啡)。
var answer;
$.ajax('/foo.json') . done(function(response) {
callback(response.data);
});
function callback(data) {
console.log(data);
}
加入承诺
order_milk() . then(put_in_coffee)
order_milk() . then(put_in_coffee) . then(drink_coffee)
function get_data() {
return $.ajax('/foo.json');
}
get_data() . then(do_something)
get_data() .
then(function(data) { console.log(data); });
get_data() .
then(data => console.log(data));
a();
b();
a() . then(b);
async function morning_routine() {
var milk = await order_milk();
var coffee = await put_in_coffee(milk);
await drink(coffee);
}
async function foo() {
data = await get_data();
console.log(data);
}