我如何从函数 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 是单一的 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 回复

其他回答

下面我写的例子表明如何

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

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

2017 答案:你现在可以做你想要的事情在每个当前的浏览器和 Node.js

这是相当简单的:

返回承诺 使用“等待”,这将告诉JavaScript等待承诺将被解决到一个值(如HTTP答案) 将“async”关键字添加到主功能

下面是您的代码工作版本:

(async function(){

    var response = await superagent.get('...')
    console.log(response)

})()

等待支持所有当前的浏览器和 Node.js 8

看看这个例子:

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

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

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框架中使用的双向数据连接或存储概念将为您工作。

因此,如果您使用 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
});