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

当前回答

我认为,无论使用哪种方法或机制,或者哪种框架(天角/反应)隐藏它,以下原则是:

在程序的流程中(思考代码或甚至最低水平:机器代码),数据可能不会在2秒后,3秒后回来,或者可能根本没有回来,所以没有常见的回来来使用,以便返回数据。

其他回答

下面我写的例子表明如何

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

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

下面是一些方法来处理无同步请求:

浏览器承诺对象 Q - 一个承诺图书馆为JavaScript A+ Promises.js jQuery 提交 XMLHttpRequest API 使用呼叫回复概念 - 作为实施在第一个答案

示例: jQuery 转移实施,以处理多个请求

應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式 應用程式

下面是一個工作的例子: 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

function ajax(a, b, c){ // URL, callback, just a placeholder
  c = new XMLHttpRequest;
  c.open('GET', a);
  c.onload = b;
  c.send()
}

正如你可以看到的那样:

最简单的:

this.response

e.target.response

例子:

function callback(e){
  console.log(this.response);
}
ajax('URL', callback);

ajax('URL', function(e){console.log(this.response)});

查看 XMLHttpRequest 先进功能。


现在,如果您想要使用 POST 和 FormData 更复杂的东西,您可以轻松地扩展此功能:

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
  c = new XMLHttpRequest;
  c.open(e||'get', a);
  c.onload = b;
  c.send(d||null)
}

使用例子:

x(url, callback); // By default it's GET so no need to set
x(url, callback, 'post', {'key': 'val'}); // No need to set POST data

或者输入完整的表格元素(document.getElementsByTagName('form')[0]):

var fd = new FormData(form);
x(url, callback, 'post', fd);

var fd = new FormData();
fd.append('key', 'val')
x(url, callback, 'post', fd);


正如评论中提到的那样,使用错误&同步完全破坏了答案的点。

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
  c = new XMLHttpRequest;
  c.open(e||'get', a);
  c.onload = b;
  c.onerror = error;
  c.send(d||null)
}

function error(e){
  console.log('--Error--', this.type);
  console.log('this: ', this);
  console.log('Event: ', e)
}
function displayAjax(e){
  console.log(e, this);
}
x('WRONGURL', displayAjax);

在第二种情况下,它只是工作,您必须在服务器侧检查是否通过了正确的邮件数据。

未允许的跨域将自动排出错误。


如果你想阻止浏览器一段时间下载一个漂亮的大.txt 文件同步。

function omg(a, c){ // URL
  c = new XMLHttpRequest;
  c.open('GET', a, true);
  c.send();
  return c; // Or c.response
}

 var res = omg('thisIsGonnaBlockThePage.txt');


如果你想扩展这个功能......

是的,你可以。

但是,你可以用 XMLHttpRequest 2 做很多事情:

但这里的问题是如何返回一个Ajax答案......(我添加了一个简单的方式)。

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