我如何从函数 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`
}

当前回答

下面是一個工作的例子: const validateName = async userName => { const url = "https://jsonplaceholder.typicode.com/todos/1"; try { const response = await axios.get(url); return response.data } catch (err) { return false; } }; validateName("user").then(data => console.log(data)).catch(reason => console.log(reason.message)).as-console-wrapper { max-height: 100%!im

其他回答

最简单的解决方案是创建一个JavaScript功能,并将其称为Ajax成功的呼叫。

function callServerAsync(){
    $.ajax({
        url: '...',
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to a JSON response
}

function foo(callback) {

    $.ajax({
        url: '...',
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);
});

你的代码应该是沿着这条线的一点:

function foo() {
    var data;
    // Or $.get(...).then, or request(...).then, or query(...).then
    fetch("/echo/json").then(function(response){
        data = response.json();
    });
    return data;
}

var result = foo(); // 'result' is always undefined no matter what.


当我们打电话给一个承诺并从中返回一些东西时,我们会得到处理的价值的承诺;如果我们返回另一个承诺,我们会得到惊人的东西,但让我们抓住我们的马。

function delay(ms){ // Takes amount of milliseconds
    // Returns a new promise
    return new Promise(function(resolve, reject){
        setTimeout(function(){ // When the time is up,
            resolve(); // change the promise to the fulfilled state
        }, ms);
    });
}

基本上,而不是返回一个值,我们不能因为竞争模式 - 我们正在返回一个值,我们可以与它无缝。

function foo() {
    // RETURN the promise
    return fetch("/echo/json").then(function(response){
        return response.json(); // Process it inside the `then`
    });
}

foo().then(function(response){
    // Access the value inside the `then`
})

function* foo(){ // Notice the star. This is ES6, so new browsers, Nodes.js, and io.js only
    yield 1;
    yield 2;
    while(true) yield 3;
}

var foo = coroutine(function*(){
    var data = yield fetch("/echo/json"); // Notice the yield
    // The code here only executes _after_ the request is done
    return data.json(); // 'data' is defined
});

var main = coroutine(function*(){
   var bar = yield foo(); // Wait our earlier coroutine. It returns a promise
   // The server call is done here, and the code below executes when done
   var baz = yield fetch("/api/users/" + bar.userid); // Depends on foo's result
   console.log(baz); // Runs after both requests are done
});
main();

2016年(ES7)

在ES7中,这一点进一步标准化了,现在有几个建议,但在所有这些建议中,你可以等待承诺,这只是ES6提议的“糖”(尼克合成)通过添加同步并等待关键词。

async function foo(){
    var data = await fetch("/echo/json"); // Notice the await
    // code here only executes _after_ the request is done
    return data.json(); // 'data' is defined
}

而不是把代码扔在你身上,有两个概念是了解JavaScript如何处理呼叫反馈和无同步性(甚至是一个词?)的关键。

活动流程和汇率模型

你需要知道的三件事:尾巴、事件圈和尾巴。

while (queue.waitForMessage()) {
  queue.processNextMessage();
}

一旦收到一个消息运行某件事,它将其添加到尾巴上,尾巴是等待执行的事情的列表(如您的AJAX请求)。

当其中一个消息将执行时,它将从字符串中打开消息并创建一个字符串,字符串是所有JavaScript需要执行以执行消息中的指示。

function foobarFunc (var) {
  console.log(anotherFunction(var));
}

因此,任何 foobarFunc 需要执行的东西(在我们的情况下,另一个功能)将被推到架子上。执行,然后被遗忘 - 事件圈将随后移动到接下来的东西在架子上(或听到消息)

这里的关键是执行命令。

什么时候会发生什么事

function foo(bla) {
  console.log(bla)
}

下面我写的例子表明如何

处理无同步的 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}" 

我在这里讨论了这个解决方案。

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);