我如何从函数 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`
}
这是其中一个地方,在许多新的JavaScript框架中使用的双向数据连接或存储概念将为您工作。
因此,如果您使用 Angular, React 或任何其他框架,使双向数据连接或存储概念,这个问题只是为您固定,所以简单地说,您的结果在第一阶段是不确定的,所以您在收到数据之前得到了结果 = 不确定的,然后一旦您获得结果,它将被更新并被分配到新的值,你的 Ajax 呼叫的反应。
但是,你如何在纯粹的JavaScript或jQuery中这样做,例如,你在这个问题上问的那样?
例如,在承诺中,我们有某些功能,如成功() 或之后() 将执行,当您的数据为您准备好。
$(document).ready(function(){
function foo() {
$.ajax({url: "api/data", success: function(data){
fooDone(data); // After we have data, we pass it to fooDone
}});
};
function fooDone(data) {
console.log(data); // fooDone has the data and console.log it
};
foo(); // The call happens here
});
选项 #1 - 从 foo 方法直接返回 Ajax 通话. 在 jQuery 的最新版本中,一个 Ajax 通话返回一个承诺的对象,可以使用.then 函数解决。
// 宣告函数 foo 函数 foo(url) {返回 $.get(url); } // 召回 foo 函数,返回一个承诺的对象 // 函数 '然后' 接受召回解决函数 foo('https://jsonplaceholder.typicode.com/todos/1').then(函数(回复) { console.log(回复); } ).as-console-wrapper { max-height: 100%!important;
选项 #2 - 宣布承诺对象并返回它. 在函数中宣布承诺对象,在承诺函数中嵌入 Ajax 呼叫,并返回承诺对象。
在阅读这里的所有回复和我的经验后,我希望重复在JavaScript中无同步编程的呼叫、承诺和Async/等待的细节。
const body = document.getElementsByTagName('body')[0];
function callback() {
console.log('Hello');
}
body.addEventListener('click', callback);
asyncCallOne(function callback1() {
asyncCallTwo(function callback2() {
asyncCallThree(function callback3() {
...
})
})
})
const myFirstPromise = new Promise((resolve, reject) => {
// We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
// In this example, we use setTimeout(...) to simulate async code.
// In reality, you will probably be using something like XHR request or an HTML5 API.
setTimeout(() => {
resolve("Success!") // Yay! Everything went well!
}, 250)
})
myFirstPromise
.then((res) => {
return res.json();
})
.then((data) => {
console.log(data);
})
.catch((e) => {
console.log(e);
});
then — Runs a callback you pass to it when the promise has fulfilled.
catch — Runs a callback you pass to it when something went wrong.
Async 函数为我们提供一个干净和细致的合成,使我们能够写得更少的代码,以实现相同的结果,我们会得到的承诺. Async/Await 看起来类似于同步代码,同步代码更容易阅读和写作。
const getExchangeRate = async () => {
try {
const res = await fetch('https://getExchangeRateData');
const data = await res.json();
console.log(data);
} catch (err) {
console.error(err);
}
}
getExchangeRate();
结论:这些完全是JavaScript中的无同步编程的三个合成,你应该明白,所以如果可能的话,我建议你使用“承诺”或“async/await”来恢复你的无同步代码(主要是XHR请求)!
而不是把代码扔在你身上,有两个概念是了解JavaScript如何处理呼叫反馈和无同步性(甚至是一个词?)的关键。
活动流程和汇率模型
你需要知道的三件事:尾巴、事件圈和尾巴。
while (queue.waitForMessage()) {
queue.processNextMessage();
}
一旦收到一个消息运行某件事,它将其添加到尾巴上,尾巴是等待执行的事情的列表(如您的AJAX请求)。
当其中一个消息将执行时,它将从字符串中打开消息并创建一个字符串,字符串是所有JavaScript需要执行以执行消息中的指示。
function foobarFunc (var) {
console.log(anotherFunction(var));
}
因此,任何 foobarFunc 需要执行的东西(在我们的情况下,另一个功能)将被推到架子上。执行,然后被遗忘 - 事件圈将随后移动到接下来的东西在架子上(或听到消息)
这里的关键是执行命令。
什么时候会发生什么事
function foo(bla) {
console.log(bla)
}
JavaScript 是单一的 threaded。
浏览器可以分为三个部分:
这是一个对一个进行的曲线,并放入事件圈,执行这个函数,并在第一次执行后为下一个做好准备,这意味着执行一个函数不会开始,直到在事件圈中执行之前的函数。
它从事件路由中取出这个功能,并与服务器进行交易,使事件路由免费,以便我们可以从路由中执行下一个功能。
假设我们的服务器Request()函数有一个返回声明的代码. 当我们从服务器 Web API 恢复数据时,它将推到尾部的尾部。
因此,这个问题的解决方案是召回或承诺。
此分類上一篇
function doAjax(callbackFunc, method, url) {
var xmlHttpReq = new XMLHttpRequest();
xmlHttpReq.open(method, url);
xmlHttpReq.onreadystatechange = function() {
if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
callbackFunc(xmlHttpReq.responseText);
}
}
xmlHttpReq.send(null);
}
在我的代码中,它被称为:
function loadMyJson(categoryValue){
if(categoryValue === "veg")
doAjax(print, "GET", "http://localhost:3004/vegetables");
else if(categoryValue === "fruits")
doAjax(print, "GET", "http://localhost:3004/fruits");
else
console.log("Data not found");
}
JavaScript.info 回复
ECMAScript 6 有“发明器”,允许您轻松地在无同步的风格编程。
function* myGenerator() {
const callback = yield;
let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
console.log("response is:", response);
// examples of other things you can do
yield setTimeout(callback, 1000);
console.log("it delayed for 1000ms");
while (response.statusText === "error") {
[response] = yield* anotherGenerator();
}
}
要运行上面的代码,你会这样做:
const gen = myGenerator(); // Create generator
gen.next(); // Start it
gen.next((...args) => gen.next([...args])); // Set its callback function
如果您需要针对不支持 ES6 的浏览器,您可以通过 Babel 或关闭编译器运行代码,以创建 ECMAScript 5。
呼叫回归器被包围在一个序列,并在你阅读它们时被破坏,以便模式可以处理有多个论点的呼叫回归器。
const [err, data] = yield fs.readFile(filePath, "utf-8", callback);