我如何从函数 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`
}
选项 #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 呼叫,并返回承诺对象。
虽然承诺和呼叫在许多情况下工作顺利,但背部疼痛是表达这样的东西:
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
}
您可以在此处查看项目。
看看这个例子:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,$http) {
var getJoke = function(){
return $http.get('http://api.icndb.com/jokes/random').then(function(res){
return res.data.value;
});
}
getJoke().then(function(res) {
console.log(res.joke);
});
});
正如你可以看到 getJoke 返回已解决的承诺(当返回 res.data.value 时,它是解决的)。所以你等到 $http.get 请求完成,然后 console.log(res.joke) 执行(作为正常的无同步流动)。
此分類上一篇: plnkr
http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/
ES6路(Async - 等待)
(function(){
async function getJoke(){
let response = await fetch('http://api.icndb.com/jokes/random');
let data = await response.json();
return data.value;
}
getJoke().then((joke) => {
console.log(joke);
});
})();
下面我写的例子表明如何
处理无同步的 HTTP 通话; 等待每个 API 通话的响应; 使用 Promise 模式; 使用 Promise.all 模式加入多个 HTTP 通话;
[
"search?type=playlist&q=%22doom%20metal%22",
"search?type=playlist&q=Adele"
]
对于每个项目,一个新的承诺将燃烧一个区块 - ExecutionBlock,打破结果,根据结果序列安排一个新的承诺集,这是 Spotify 用户对象的列表,并在 ExecutionProfileBlock 中无同步执行新的 HTTP 通话。
然后,你可以看到一个被遗弃的承诺结构,允许你扫描多个和完全无同步的遗弃的HTTP通话,并通过 Promise.all 加入每个子组的通话的结果。
-H "Authorization: Bearer {your access token}"
我在这里讨论了这个解决方案。
问题是:
我如何从无同步通话中返回答案?
可以被解释为:
如何让同步代码看起来同步?
解决方案将是避免呼叫,并使用一个组合的承诺和async/await。
我想举一个例子给一个Ajax请求。
(虽然它可以用JavaScript写作,但我宁愿用Python写作,并用Transcrypt编写到JavaScript。
首先,让我们启用 jQuery 使用,以便有 $ 作为 S 可用:
__pragma__ ('alias', 'S', '$')
设置一个函数返回承诺,在这种情况下,一个Ajax呼叫:
def read(url: str):
deferred = S.Deferred()
S.ajax({'type': "POST", 'url': url, 'data': { },
'success': lambda d: deferred.resolve(d),
'error': lambda e: deferred.reject(e)
})
return deferred.promise()
使用非同步代码,就好像它是同步的:
async def readALot():
try:
result1 = await read("url_1")
result2 = await read("url_2")
except Exception:
console.warn("Reading a lot failed")