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

当前回答

角质1

使用AngularJS的人可以通过承诺来处理这种情况。

這裡說,

承诺可以用于无与伦比的功能,并允许一个连接多个功能。

你也可以在这里找到一个好解释。

下面提到的文档中有一个例子。

  promiseB = promiseA.then(
    function onSuccess(result) {
      return result + 1;
    }
    ,function onError(err) {
      // Handle error
    }
  );

 // promiseB will be resolved immediately after promiseA is resolved
 // and its value will be the result of promiseA incremented by 1.

孔子2及以后

在 Angular 2 中,请参见下面的例子,但建议使用 Angular 2 的观察器。

 search(term: string) {
     return this.http
       .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
       .map((response) => response.json())
       .toPromise();
}

你可以用这种方式,

search() {
    this.searchService.search(this.searchField.value)
      .then((result) => {
    this.result = result.artists.items;
  })
  .catch((error) => console.error(error));
}

但TypeScript不支持本地ES6承诺,如果你想使用它,你可能需要插件。

此外,这里是承诺的规格。

其他回答

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

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

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

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

看看这个例子:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope,$http) {

    var getJoke = function(){
        return $http.get('http://api.icndb.com/jokes/random').then(function(res){
            return res.data.value;  
        });
    }

    getJoke().then(function(res) {
        console.log(res.joke);
    });
});

正如你可以看到 getJoke 返回已解决的承诺(当返回 res.data.value 时,它是解决的)。所以你等到 $http.get 请求完成,然后 console.log(res.joke) 执行(作为正常的无同步流动)。

此分類上一篇: plnkr

http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/

ES6路(Async - 等待)

(function(){
  async function getJoke(){
    let response = await fetch('http://api.icndb.com/jokes/random');
    let data = await response.json();
    return data.value;
  }

  getJoke().then((joke) => {
    console.log(joke);
  });
})();

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

结果和文档

此分類上一篇


而不是把代码扔在你身上,有两个概念是了解JavaScript如何处理呼叫反馈和无同步性(甚至是一个词?)的关键。

活动流程和汇率模型

你需要知道的三件事:尾巴、事件圈和尾巴。

while (queue.waitForMessage()) {
  queue.processNextMessage();
}

一旦收到一个消息运行某件事,它将其添加到尾巴上,尾巴是等待执行的事情的列表(如您的AJAX请求)。

当其中一个消息将执行时,它将从字符串中打开消息并创建一个字符串,字符串是所有JavaScript需要执行以执行消息中的指示。

function foobarFunc (var) {
  console.log(anotherFunction(var));
}

因此,任何 foobarFunc 需要执行的东西(在我们的情况下,另一个功能)将被推到架子上。执行,然后被遗忘 - 事件圈将随后移动到接下来的东西在架子上(或听到消息)

这里的关键是执行命令。

什么时候会发生什么事

function foo(bla) {
  console.log(bla)
}

使用 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) }。