【问题标题】:cannot order js function execution using promises无法使用 Promise 命令执行 js 函数
【发布时间】:2017-10-16 18:20:46
【问题描述】:

基本上,我需要 2 个函数 A 和 B 来获取数据,然后我想在成功获取数据后运行函数 C

这是我的代码:

JS:

var A = function() {

  $.getJSON('linkA', function(data) {
    a = data.total;
    console.log("A : " + a);
  });

  return new Promise(function(resolve, reject) {
    resolve('Got a');
  });
};

var B = function() {

  $.getJSON('linkB', function(data) {
    b = data.total;
    console.log("B:" + b);
  });

  return new Promise(function(resolve, reject) {
    resolve('Got b');
  });
};

function run() {
  Promise.all([A(), B()]).then(function() {
    console.log("Got A and B")
  });
}

HTML:

<script>
run();
</script>

我希望结果应该在控制台中:

A: //数据

B: //数据

得到A和B

但是,我仍然在其他两行之前得到了“Got A and B”。我猜是因为获取数据需要很长时间,所以程序首先编写“得到 A 和 B”。但必须有某种方式来实现目标??

【问题讨论】:

  • 您需要将您的return new Promise(function(resolve, reject) { ... 放入$.getJSON('linkB', function(data) {... 回调函数中。
  • 小错误 Promise.all([A, B]).then(function() { console.log("Got A and B") });为此更改您的代码
  • @Krusader 不,OP 需要解决 getJSON 函数中的承诺。
  • 我还需要把它放在 getJson('linkA') 中吗?
  • @ÁlvaroTouzón:不,OP 正确调用AB

标签: javascript html css json promise


【解决方案1】:

您会立即解决承诺,而不是等到您取回数据。

你也成为了 Promise 创建反模式的牺牲品。 $.getJSON 已经给了你一个 thenable*,所以只需使用它并使用 then 来转换数据(通过访问 total):

var A = function() {
  return $.getJSON('linkA').then(function(data) {
    return data.total;
  });
};

B 也是如此。然后你的Promise.all 代码就可以工作了,如果你调整它,你实际上可以得到ab

function run() {
  Promise.all([A(), B()]).then(function(results) {
    var a = results[0], b = results[1];
    // ...use `a` and `b`...
  });
}

或者如果你可以依赖 ES2015+ 的特性,你可以使用箭头函数和解构(如果你愿意,也可以使用普通函数和解构):

function run() {
  Promise.all([A(), B()]).then(([a, b]) => {
    // ...use `a` and `b`...
  });
}

由于您的其余代码仅依赖于 jQuery,而不是浏览器中的 Promise 支持,您也可以使用 jQuery 的$.when

function run() {
  $.when(A(), B()).then(function(a, b) {
    // ...use `a` and `b`...
  });
}

如果您需要明确地执行new Promise(您不需要在这里)来与非 thenable API 接口,它看起来像这样:

// YOU DON'T NEED TO DO THIS WITH $.getJSON, but with non-thenable APIs you might
var A = function() {
  return new Promise(function(resolve, reject) {
    $.getJSON('linkA', function(data) {
      resolve(data.total);
    }).fail(function(jqXHR, textStatus, errorThrown) {
      reject(errorThrown || new Error(textStatus));
    });
  });
};

* "thenable" - 类似于 Promise 的东西,参见 the Promises/A+ spec

【讨论】:

  • 那么我需要在 A 和 B 函数中创建“新承诺”吗?
  • @NgocTuanLam:不,您需要AB 中创建新的承诺。毕竟,你已经有了一个(来自$.getJSON)。
  • 注意:如果您在上面的第一个代码块中没有看到 then,请点击刷新。
  • 哇,谢谢,我使用了你的前 2 个代码块,它可以工作,但是,使用 var a = results[0] , b = results[1];在你的第二个街区。我实际得到的 a 和 b 是 2 个对象,而不是数据。所以我通过在 A 和 B 函数中分配 a 和 b 并在 run() 函数中控制台记录 a 和 b 来修复它。我会尝试你的其他建议。谢谢
  • @NgocTuanLam:是的,我很晚才发现这一点,这是我 “注意:如果你没有看到 then...” 评论的原因。
【解决方案2】:

var url = 'https://jsonplaceholder.typicode.com/posts/';

Promise.all( [url + 1, url + 2 ].map( $.get ) )
  .then(
   console.log
  )
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    相关资源
    最近更新 更多