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

当前回答

另一个解决方案是通过序列执行器 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 将逐步评估所有运营商和表达式,如果某些缓慢功能的结果不准备好,则停止执行。

这里有更多的例子。

其他回答

标签: 假

我通过将 async 设置为虚假,并重组我的 Ajax 呼叫:

我设置了一个全球性函数,称为 sendRequest(类型,URL,数据),有三个参数,每次在任何地方都会被召唤:

function sendRequest(type, url, data) {
    let returnValue = null;
    $.ajax({
        url: url,
        type: type,
        async: false,
        data: data,
        dataType: 'json',
        success: function (resp) {
            returnValue = resp;
        }
    });
    return returnValue;
}

接下来的函数:

let password = $("#password").val();
        let email = $("#email").val();
        let data = {
            email: email,
            password: password,
        };
        let  resp =  sendRequest('POST', 'http://localhost/signin')}}", data);
        console.log(resp);

此分類上一篇: async: false

如果这个解决方案不与您合作,请注意,这可能不会在某些浏览器或jQuery版本工作。

如果您不使用 jQuery 在您的代码中,这个答案是为您

function foo() {
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', "/echo/json");
    httpRequest.send();
    return httpRequest.responseText;
}

var result = foo(); // Always ends up being 'undefined'

(注意,对于使用新的Fetch API、Angular 或承诺的人,我在下面添加了另一个答案)


你所面临的

这里有一个简单的模拟:

function getFive(){
    var a;
    setTimeout(function(){
         a=5;
    },10);
    return a;
}

(重定向)

function onComplete(a){ // When the code completes, do this
    alert(a);
}

function getFive(whenDone){
    var a;
    setTimeout(function(){
         a=5;
         whenDone(a);
    },10);
}

使用将是:

getFive(onComplete);

同步AJAX - 不要这样做!!!

var request = new XMLHttpRequest();
request.open('GET', 'yourURL', false);  // `false` makes the request synchronous
request.send(null);

if (request.status === 200) {// That's HTTP for 'ok'
  console.log(request.responseText);
}

二、修复代码

如:

var result = foo();
// Code that depends on `result` goes here

变成:

foo(function(result) {
    // Code that depends on `result`
});

function myHandler(result) {
    // Code that depends on `result`
}
foo(myHandler);

function foo(callback) {
    var httpRequest = new XMLHttpRequest();
    httpRequest.onload = function(){ // When the request is loaded
       callback(httpRequest.responseText);// We're calling our method
    };
    httpRequest.open('GET', "/echo/json");
    httpRequest.send();
}

我们现在已经使我们的 foo 函数接受一个行动运行,当 AJAX 成功完成时,我们可以通过检查答案状态是否不为 200 进行进一步扩展,并按照此进行操作(创建一个错误处理器等)。

如果你仍然很难理解这一点,请阅读MDN的AJAX开始指南。

使用 ES2017 您应该将此作为功能声明。

async function foo() {
  var response = await $.ajax({url: '...'})
  return response;
}

这样执行它。

(async function() {
  try {
    var result = await foo()
    console.log(result)
  } catch (e) {}
})()

或承诺的合成。

foo().then(response => {
  console.log(response)

}).catch(error => {
  console.log(error)

})

Stack Snippet 显示上面的代码。

// 函数声明: async 函数 foo() { var 回复 = 等待 $.ajax({ url: 'https://jsonplaceholder.typicode.com/todos/1' }) 返回回回复; } // 执行此类: (async 函数() { 尝试 { var 结果 = 等待 foo() console.log(result) } 捕捉(e) {} }() // 或使用 承诺 合成: foo().then(回复 => { console.log(response) }。

另一个解决方案是通过序列执行器 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 将逐步评估所有运营商和表达式,如果某些缓慢功能的结果不准备好,则停止执行。

这里有更多的例子。

这是其中一个地方,在许多新的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
});