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

当前回答

虽然承诺和呼叫在许多情况下工作顺利,但背部疼痛是表达这样的东西:

if (!name) {
  name = async1();
}
async2(name);

您最终会通过 async1; 检查名称是否不定义,并根据此呼叫回复。

async1(name, callback) {
  if (name)
    callback(name)
  else {
    doSomething(callback)
  }
}

async1(name, async2)

雖然在小例子中很好,但當你有許多類似案例和錯誤處理涉及時,它會變得令人不安。

纤维可以帮助解决这个问题。

var Fiber = require('fibers')

function async1(container) {
  var current = Fiber.current
  var result
  doSomething(function(name) {
    result = name
    fiber.run()
  })
  Fiber.yield()
  return result
}

Fiber(function() {
  var name
  if (!name) {
    name = async1()
  }
  async2(name)
  // Make any number of async calls from here
}

您可以在此处查看项目。

其他回答

我会用可怕的看起来,手拍的漫画来回答,第二张图像是为什么结果在您的代码示例中无法定义的原因。

此分類上一篇

另一种方法是从无同步函数中返回值,是通过将结果从无同步函数中存储的对象。

下面是相同的例子:

var async = require("async");

// This wires up result back to the caller
var result = {};
var asyncTasks = [];
asyncTasks.push(function(_callback){
    // some asynchronous operation
    $.ajax({
        url: '...',
        success: function(response) {
            result.response = response;
            _callback();
        }
    });
});

async.parallel(asyncTasks, function(){
    // result is available after performing asynchronous operation
    console.log(result)
    console.log('Done');
});

我正在使用结果对象来存储在无同步操作期间的值,这使得结果即使在无同步工作后也可用。

我使用这个方法很多,我会感兴趣知道这个方法有多好运作,在那里通过连续模块将结果传输回来。

标签: 假

我通过将 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版本工作。

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

简单的代码例子将 XHR 在 Node.js 转换为 async-await

var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var xhttp = new XMLHttpRequest();

function xhrWrapWithPromise() {
  return new Promise((resolve, reject) => {
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4) {
        if (this.status == 200) {
          resolve(this.responseText);
        } else {
          reject(new Error("Couldn't feth data finally"));
        }
      }
    };
    xhttp.open("GET", "https://www.w3schools.com/xml/xmlhttp_info.txt", true);
    xhttp.send();
  });
}

// We need to wrap await in Async function so and anonymous IIFE here
(async _ => {
  try {
    let result = await xhrWrapWithPromise();
    console.log(result);
  } catch (error) {
    console.log(error);
  }
})();