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

当前回答

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答案......(我添加了一个简单的方式)。

其他回答

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

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

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

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

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

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

另一个解决方案是通过序列执行器 nsynjs 执行代码。

nsynjs 将连续评估所有承诺,并将承诺结果列入数据属性:

函数同步Code() { var getURL = 函数(url) { return window.fetch(url).data.text().data; }; var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'; console.log('收到的比特:',getURL(url).length); }; nsynjs.run(同步Code,{},函数(){ console.log('同步Code done'); }; <script src="https://rawgit.com/amaksr/

如果基本功能不承诺

步骤 1 将函数与呼叫回归到 nsynjs-aware 插槽中(如果它有一个有前途的版本,你可以错过这个步骤):

var ajaxGet = function (ctx,url) {
    var res = {};
    var ex;
    $.ajax(url)
    .done(function (data) {
        res.data = data;
    })
    .fail(function(e) {
        ex = e;
    })
    .always(function() {
        ctx.resume(ex);
    });
    return res;
};
ajaxGet.nsynjsHasCallback = true;

function process() {
    console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
}

步骤3:通过 nsynjs 以同步方式运行函数:

nsynjs.run(process,this,function () {
    console.log("synchronous function finished");
});

Nsynjs 将逐步评估所有运营商和表达式,如果某些缓慢功能的结果不准备好,则停止执行。

这里有更多的例子。

起初,呼叫反馈被用于无同步操作(例如,在XMLHttpRequest API)。现在,像浏览器的Fetch API这样的基于承诺的APIs已成为默认解决方案,并且所有现代浏览器和Node.js(服务器侧)都支持更轻松的async/await合成。

一个常见的场景 - 从服务器中获取 JSON 数据 - 可以看起来如下:

async function fetchResource(url) {
  const res = await fetch(url);
  if (!res.ok) {
    throw new Error(res.statusText);
  }
  return res.json();
}

在另一个功能中使用:

async function doSomething() {
  try {
    const data = await fetchResource("https://example.test/resource/1");
    // ...
  } catch (e) {
    // Handle error
    ...
  }
}

如果你设计一个现代的API,强烈建议你更喜欢基于承诺的风格,而不是呼叫回复,如果你继承了一个基于呼叫回复的API,你可以把它作为承诺:

function sleep(timeout) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, timeout);
  });
}

async function fetchAfterTwoSeconds(url) {
  await sleep(2000);
  return fetchResource(url);
}

在Node.js中,历史上仅依赖于呼叫反馈,这种技术是如此常见,以至于它们添加了一个名为util.promisify的辅助功能。

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 回复