我如何从函数 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`
}
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);
让我们从一个简单的JavaScript功能开始:
function foo(){
// Do something
return 'wohoo';
}
let bar = foo(); // 'bar' is 'wohoo' here
这是一个简单的同步函数呼叫(每个字符串的代码在下一个字符串之前“完成”),结果是相同的预期。
function foo(){
setTimeout( ()=> {
return 'wohoo';
}, 1000)
}
let bar = foo() // 'bar' is undefined here
所以你去那里;那个延迟只是打破了我们所期望的功能!但是发生了什么事? 好吧,如果你看代码,它真的很合乎逻辑。
承诺实际上是关于它意味着什么:它意味着该功能保证你提供它在未来得到的任何产量。
function foo(){
return new Promise((resolve, reject) => { // I want foo() to PROMISE me something
setTimeout ( function(){
// Promise is RESOLVED, when the execution reaches this line of code
resolve('wohoo') // After 1 second, RESOLVE the promise with value 'wohoo'
}, 1000 )
})
}
let bar;
foo().then( res => {
bar = res;
console.log(bar) // Will print 'wohoo'
});
更新(与 async/await 承诺)
此分類上一篇: Catch Version:
function saveUsers(){
getUsers()
.then(users => {
saveSomewhere(users);
})
.catch(err => {
console.error(err);
})
}
async/await 版本:
async function saveUsers(){
try{
let users = await getUsers()
saveSomewhere(users);
}
catch(err){
console.error(err);
}
}
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);
}
标签: 假
我通过将 async 设置为虚假,并重组我的 Ajax 呼叫:
我设置了一个全球性函数,称为 sendRequest(类型,URL,数据),有三个参数,每次在任何地方都会被召唤:
function sendRequest(type, url, data) {
let returnValue = null;
$.ajax({
url: url,
type: type,
async: false,
data: data,
dataType: 'json',
success: function (resp) {
returnValue = resp;
}
});
return returnValue;
}
接下来的函数:
let password = $("#password").val();
let email = $("#email").val();
let data = {
email: email,
password: password,
};
let resp = sendRequest('POST', 'http://localhost/signin')}}", data);
console.log(resp);
此分類上一篇: async: false
如果这个解决方案不与您合作,请注意,这可能不会在某些浏览器或jQuery版本工作。
虽然承诺和呼叫在许多情况下工作顺利,但背部疼痛是表达这样的东西:
if (!name) {
name = async1();
}
async2(name);
您最终会通过 async1; 检查名称是否不定义,并根据此呼叫回复。
async1(name, callback) {
if (name)
callback(name)
else {
doSomething(callback)
}
}
async1(name, async2)
雖然在小例子中很好,但當你有許多類似案例和錯誤處理涉及時,它會變得令人不安。
纤维可以帮助解决这个问题。
var Fiber = require('fibers')
function async1(container) {
var current = Fiber.current
var result
doSomething(function(name) {
result = name
fiber.run()
})
Fiber.yield()
return result
}
Fiber(function() {
var name
if (!name) {
name = async1()
}
async2(name)
// Make any number of async calls from here
}
您可以在此处查看项目。