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

当前回答

使用 async/await 与一个 transpilers 如 Babel 让它工作在较老的浏览器. 你还需要安装这个 Babel 预定和 polyfill 从 npm: npm i -D babel-preset-env babel-polyfill。

function getData(ajaxurl) { 
  return $.ajax({
    url: ajaxurl,
    type: 'GET',
  });
};

async test() {
  try {
    const res = await getData('https://api.icndb.com/jokes/random')
    console.log(res)
  } catch(err) {
    console.log(err);
  }
}

test();

或者.then callback 只是写同样的逻辑的另一种方式。

getData(ajaxurl).then(function(res) {
    console.log(res)
}

其他回答

最简单的解决方案是创建一个JavaScript功能,并将其称为Ajax成功的呼叫。

function callServerAsync(){
    $.ajax({
        url: '...',
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to a JSON response
}

function foo(callback) {

    $.ajax({
        url: '...',
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);
});

urls = ['https://jsonplaceholder.typicode.com/todos/2',
        'https://jsonplaceholder.typicode.com/todos/3']

{"userId":1,"id":2,"title":"quis ut nam facilis et officia qui",
 "completed":false}
{"userId":1,"id":3,"title":"fugiat veniam minus","completed":false}

namesonly = ['two', 'three']

[{"name":"two","loremipsum":"quis ut nam facilis et officia qui"},
{"name":"three","loremipsum":"fugiat veniam minus"}]

...
  "release-groups": [
    {
      "id": "1dc4c347-a1db-32aa-b14f-bc9cc507b843",
      "secondary-type-ids": [],
      "first-release-date": "2000-07-10",
      "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc",
      "disambiguation": "",
      "secondary-types": [],
      "title": "Parachutes",
      "primary-type": "Album"
    },
...

此 JSON 剪辑显示 Coldplay 的第一张专辑是 Parachutes. 它还提供了一个 ID,在这种情况下 1dc4c347-a1db-32aa-b14f-bc9cc507b843,这是专辑的独特标识。

对于每个专辑,JSON答案包含一些图像,其中一个是专辑的前面覆盖。

{
  "images": [
    {
      "approved": true,
      "back": false,
      "comment": "",
      "edit": 22132705,
      "front": true,
      "id": 4086974851,
      "image": "http://coverartarchive.org/release/435fc965-9121-461e-b8da-d9b505c9dc9b/4086974851.jpg",
      "thumbnails": {
        "250": "http://coverartarchive.org/release/435fc965-9121-461e-b8da-d9b505c9dc9b/4086974851-250.jpg",
        "500": "http://coverartarchive.org/release/435fc965-9121-461e-b8da-d9b505c9dc9b/4086974851-500.jpg",
        "1200": "http://coverartarchive.org/release/435fc965-9121-461e-b8da-d9b505c9dc9b/4086974851-1200.jpg",
        "large": "http://coverartarchive.org/release/435fc965-9121-461e-b8da-d9b505c9dc9b/4086974851-500.jpg",
= = >   "small": "http://coverartarchive.org/release/435fc965-9121-461e-b8da-d9b505c9dc9b/4086974851-250.jpg"
    },
...

这里有兴趣的是“小”的线:“http://coverartarchive.org/release/435fc965-9121-461e-b8da-d9b505c9dc9b/4086974851-250.jpg”。

创建和视觉化Mashup的代码

const lock = setTimeout(() => {}, 43210);
const albumsArray = [];
const urlsArray = [];
const urlOuter = 'https://musicbrainz.org/ws/2/artist/' +
  pm.collectionVariables.get('MBID') + '?fmt=json&inc=url-rels+release-groups';
pm.sendRequest(urlOuter, (_, responseO) => {
  const bandName = responseO.json().name;
  const albums = responseO.json()['release-groups'];
  for (const item of albums) {
    albumsArray.push(item.title);
    urlsArray.push('https://coverartarchive.org/release-group/' + item.id);
  }
  albumsArray.length = urlsArray.length = 15;
  const images = [];
  let countDown = urlsArray.length;
  urlsArray.forEach((url, index) => {
    asynchronousCall(url, imageURL => {
      images[index] = imageURL;
      if (--countDown === 0) { // Callback for ALL starts on next line.
        clearTimeout(lock); // Unlock the timeout.
        const albumTitles = albumsArray.map(value => ({ title: value }));
        const albumImages = images.map(value => ({ image: value }));
        const albumsAndImages = albumTitles.map(
          (item, i) => Object.assign({}, item, albumImages[i]));
        const template = `<table>
          <tr><th>` + bandName + `</th></tr>
          {{#each responseI}}
          <tr><td>{{title}}<br><img src="{{image}}"></td></tr>
          {{/each}}
        </table>`;
        pm.visualizer.set(template, { responseI: albumsAndImages });
      }
    });
  });
  function asynchronousCall (url, callback) {
    pm.sendRequest(url, (_, responseI) => {
      callback(responseI.json().images.find(obj => obj.front === true)
        .thumbnails.small); // Individual callback.
    });
  }
});

结果和文档

此分類上一篇


如果您不使用 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) }。

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