Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ES6生成器-它们真的是异步/等待的替代品吗?_Javascript_Typescript_Async Await_Generator_Ecmascript 6 - Fatal编程技术网

Javascript ES6生成器-它们真的是异步/等待的替代品吗?

Javascript ES6生成器-它们真的是异步/等待的替代品吗?,javascript,typescript,async-await,generator,ecmascript-6,Javascript,Typescript,Async Await,Generator,Ecmascript 6,typescript博客帖子评论部分的一篇帖子说: 如果我要等到2.0才能得到ES6发电机的支持,我会 坚持使用Traceur。发电机是一件大事,他们给你 AsiNc/Apple等待今天使用库,如膝关节炎,蓝,蓝鸟, 等等 Async/await关键字允许应用程序保留类似于同步代码的逻辑结构。如何使用发电机来完成类似的事情?例如,如何将生成器与ajax调用结合使用,以生成避免使用回调的同步样式代码 例如,如何将生成器与ajax调用结合使用,以生成避免使用回调的同步样式代码 发件人: 作为一个思

typescript博客帖子评论部分的一篇帖子说:

如果我要等到2.0才能得到ES6发电机的支持,我会 坚持使用Traceur。发电机是一件大事,他们给你 AsiNc/Apple等待今天使用库,如膝关节炎,蓝,蓝鸟, 等等

Async/await关键字允许应用程序保留类似于同步代码的逻辑结构。如何使用发电机来完成类似的事情?例如,如何将生成器与ajax调用结合使用,以生成避免使用回调的同步样式代码

例如,如何将生成器与ajax调用结合使用,以生成避免使用回调的同步样式代码

发件人:


作为一个思想实验,设想以下方法,告诉JavaScript运行时暂停执行承诺中使用的wait关键字上的代码,并仅在函数返回的承诺得到解决时恢复一次

// Not actual code. A thought experiment
async function foo() {
    try {
        var val = await getMeAPromise();
        console.log(val);
    }
    catch(err){
        console.log('Error: ',err.message);
    }
}
当承诺解决时,执行继续,如果它被实现,那么等待将返回值,如果它被拒绝,将同步抛出一个错误,我们可以捕获该错误。这突然(神奇地)使异步编程和同步编程一样简单。需要三件事:

  • 暂停函数执行的能力
  • 能够在函数内部返回值
  • 能够在函数内部引发异常
好消息是,这种魔术非常真实,今天就可以尝试。语法将略有不同,因为我们将使用的技术并不仅仅是为此而设计的。这是有可能的,因为JavaScript生成器是ECMAScript 6附带的一项技术,您现在可以使用它



生成器允许您暂停函数执行(使用
yield
关键字)在内部返回值(使用
.next(val)
函数)并在内部抛出和异常(使用
.throw(err)
函数)。书中对这些API进行了解释,您也可以在generator文档中查看它们。尽管如此,您仍然应该在不了解确切API的情况下获得点/幂,因为您现在已经知道了相关性。

您只需使用辅助函数来抽象它

假设jQuery:

function ajax(type, url, data){
  $.ajax({
    url: url,
    data: data,
    type: type
  })
  .done(function(data) {
    iterator.next(data);
  })
  .fail(function() {
    iterator.throw();
  });
}
var get = ajax.bind(null, 'GET');
var post = ajax.bind(null, 'POST');
var put = ajax.bind(null, 'PUT');
var patch = ajax.bind(null, 'PATCH');
var del = ajax.bind(null, 'DELETE');

function *asyncGet() {
  var URL = 'https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow'
  var data = yield get(URL);
  console.log(data);
}

var iterator = asyncGet();
iterator.next();
另一个使用
setTimeout
的示例:

function delayReturn(time, val){
  setTimeout(function(){
    iterator.next(val);
  }, time);
}
var delayReturn1s = delayReturn.bind(null, 1000);

function *main() {
  console.log(yield delayReturn1s('Lolcat'));
}

var iterator = main();
iterator.next()
当然,您可以通过以下方式抽象迭代器传递:

var async = function(generator){
  var resume = function(err, data){
    if (err) iterator.throw();
    iterator.next(data);
  }
  var iterator = generator(resume);
  iterator.next();
}
然后你可以简单地:

function ajax(type, url, data, cb){
  $.ajax({
    url: url,
    data: data,
    type: type
  })
  .done(function(data) {
    cb(null, data)
  })
  .fail(function() {
    cb(arguments);
  });
}
var get = ajax.bind(null, 'GET');
var post = ajax.bind(null, 'POST');
var put = ajax.bind(null, 'PUT');
var patch = ajax.bind(null, 'PATCH');
var del = ajax.bind(null, 'DELETE');

async(function *(resume) {
  var URL = 'https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow'
  var data = yield get(URL, null, resume);
  console.log(data);
});

来自托马斯·亨特的博客帖子

阶段3:Generators/Yields(ES6)展示了使用ES6生成器执行异步JavaScript的示例。然而,这只是为了演示,很可能您不想使用此技术。将async/await与ES7(实验性)到ES5传输工具(如Babel或TypeScript)一起使用

var generator = publishLevel(12, {data: true});

generator.next().value.then(function(user) {
   return generator.next(user).value.then(function(can_create) {
     return generator.next(can_create).value.then(function(level_result) {
       console.log(level_result);
     });
   });
 });

function * publishLevel(user_id, level_data) {
  var user = yield getUser(user_id);
  var can_create = yield canCreate(user);

  if (!can_create) {
    return null;
  }

  var level = yield saveLevel(user, level_data);

  return level;
}

function getUser(user_id) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({
        id: user_id,
        nickname: 'tlhunter'
      });
    }, 100);
  });
}

function canCreate(user) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(user.id === 12);
    }, 100);
  });
}

function saveLevel(user, data) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve({
        id: 100,
        owner: user.nickname,
        data: data
      });
    }, 100);
  });
}

这可能有帮助:。AsYNC/AWE可以作为发电机+承诺的语法糖来实现。你简单地看了膝关节炎、一氧化碳和蓝鸟吗?它们有很好的文档记录。可能是@FelixKling的副本。谢谢你的链接-非常有用。如果你想把它作为一个答案,我会接受的。似乎我的问题的答案是肯定的。@ JeremyDanyow:是的,它有点隐藏在Koa。相反,请看一看,这里有几个使用生成器进行异步编程的库,例如。但IMO目前最好的选择是,因为它为转换后的源代码提供了多种选择。如果您关心浏览器的兼容性,您可能希望使用常规的ECMAScript 3输出,但它也可以选择将输出设置为ES6生成器(使用“galaxy”库)。async/await的部分目的是让您可以自由编写语法清晰的代码,而不必求助于这样的“选项”。是的,这基本上是一样的,但实际上还是不一样,因为语法与async/await的语义一样重要。当然,这不是一回事。OP询问如何使用生成器实现异步/等待。只是指出一个重要的区别。注意……OP正在寻找不使用回调的解决方案……async()函数仍然需要回调。有什么办法可以避免吗?我不这么认为。无论如何,您并没有使用回调返回数据,您只是用生成器包装代码。里面的代码不需要回调。例如,您可以多次尝试使用
yield get
,我认为这可能是由于使用了
console.log(data)
。如果您确实需要处理数据,那么函数*(resume)实际上是对async()的回调,因为它是针对每个用例的。类似地,如果您想使异步位更通用,那么您需要在某个地方使用回调,或者需要使用承诺。无论如何,这是一个非常接近的解决方案,但我只想指出,它并没有完全实现async/await带来的简单性如果async/await不是ES6的一部分,您将如何在6到5的transpiler中使用它们?它在幕后使用承诺,因此在ES5中运行。async/await当然是一些建议,但一些像TypeScript这样的Transpiler为您提供了实验支持选项。好的,修复了它。应该使用ES7(实验)到ES5 traspiler。如果您可以编写一个异步/等待示例exampe,相当于其中一个生成器示例,作为在这里学习这两个示例的绊脚石的参考,那就太好了。