javascript - 使用生成器异步调用列表中的每个项目

标签 javascript asynchronous promise generator yield

我不知道如何正确地写这个问题的标题,但我会解释我的问题:

假设有一个包含一些数据的列表,例如:["first", "second", "third"]

还有一个 AJAX 调用对其参数执行某些操作,例如:

function ajax(data){
  return new Promise(function (resolve, reject) {
    setTimeout(() => resolve(data+"1"), 2000)
  });
}

对于每个 AJAX 调用,您都需要一个后续操作,例如:

ajax(e).done(data => d.resolve(data+"2"));

现在我想对列表中的每个项目异步进行 AJAX 调用和后续操作,但希望等待(非阻塞)直到每个项目完成。

对于解决方案,我想使用生成器和 co library .

仅对每个列表项异步运行 AJAX 调用效果很好:

var consoleLine = "<p class=\"console-line\"></p>";

console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};

co(function*(){
  let res = yield ["first", "second", "third"].map(e => ajax(e));
  res.forEach((a, b, c) => console.log(a));
});

function ajax(data){
  return new Promise(function (resolve, reject) {
  	    setTimeout(() => resolve(data+"1"), 2000)
  });
}
.console-line
{
    font-family: monospace;
    margin: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/tj/co/master/index.js"></script>

<div id="console-log"></div>

但是通过后续操作运行它不起作用:

var consoleLine = "<p class=\"console-line\"></p>";

console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};

co(function*(){
  let res = yield test(["first", "second", "third"]);
  res.forEach((a, b, c) => console.log(a));
});

function test(g) {
  return g.map(e => function(){
    let d = new $.Deferred();
    ajax(e).done(data => d.resolve(data+"2"));
  	return d.promise();
  });
}

function ajax(data){
  return new Promise(function (resolve, reject) {
  	    setTimeout(() => resolve(data+"1"), 2000)
  });
}
.console-line
{
    font-family: monospace;
    margin: 2px;
}
<script src="https://raw.githubusercontent.com/tj/co/master/index.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="console-log"></div>

这是为什么呢?如何让我的要求发挥作用?

最佳答案

这是你的问题:

return g.map(e => function(){
//             ^^ ^^^^^^^^^^
    let d = new $.Deferred();
    ajax(e).done(data => d.resolve(data+"2"));
    return d.promise();
});

这是一个返回函数表达式的箭头函数。你要么想要

return g.map(function(e) {

return g.map(e => {

让它工作,否则你只会返回一个函数数组(并且co会以奇怪的方式处理它)。


是的,you definitely should use then而不是 done + deferreds。

关于javascript - 使用生成器异步调用列表中的每个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39063048/

相关文章:

javascript - AngularJs $q.defer() 不工作

javascript - 如何使用 "q"模块重构 mongoose 代码?

javascript - 有什么方法可以防止 Stackblitz 中的共享、 fork 选项

javascript - 如何在 Atom-Shell 中运行 reload() 和 open()

http - Guzzle 5.3 - 获取异步请求的请求持续时间

javascript - 尝试在 node.js 中使用 promise 时出错

javascript - 修改 svg :path using d3

javascript - IE 6 JQuery 切换类错误!帮助!

ios - 不使用 AFImageRequestOperation 的 AFNetworking 图片下载

flutter - Dart Future。等待多个 future 并获得不同类型的结果