首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ES6生成器--它们真的是异步/等待的替代品吗?

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

Stack Overflow用户
提问于 2014-12-01 20:44:51
回答 3查看 5.7K关注 0票数 5

打字本博客评论部分中的一篇文章写道:

如果我必须等到2.0才能获得ES6生成器支持,我就会坚持使用Traceur。生成器是一件大事,它们现在使用诸如Koa、Co、Bluebird等库提供异步/等待支持。

异步/等待关键字将允许应用程序保留类似同步代码的逻辑结构。如何使用生成器来完成类似的任务?例如,如何结合ajax调用使用生成器来生成避免使用回调的同步样式代码?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-22 23:09:42

你只需要用一个辅助函数来抽象它。

假设jQuery:

代码语言:javascript
复制
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的另一个示例

代码语言:javascript
复制
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()

当然,您可以将迭代器抽象为这样的内容:

代码语言:javascript
复制
var async = function(generator){
  var resume = function(err, data){
    if (err) iterator.throw();
    iterator.next(data);
  }
  var iterator = generator(resume);
  iterator.next();
}

然后你可以简单地:

代码语言:javascript
复制
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);
});
票数 5
EN

Stack Overflow用户

发布于 2014-12-01 22:58:47

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

来自起始Node.js

作为一个思想实验,设想如下所示,一种方法可以告诉JavaScript运行时暂停执行用于允诺的等待关键字上的代码,然后只恢复一次(如果)函数返回的承诺已经确定。

代码语言:javascript
复制
// 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,您还可以在生成器文档中查看它们。尽管如此,即使您不了解确切的API,也应该得到重点/能力,因为您现在已经知道了相关性。

票数 1
EN

Stack Overflow用户

发布于 2015-09-19 20:30:54

来自Thomas的博客文章在JavaScript中实现异步/等待的漫长道路

阶段3:生成器/产量( ES6 )展示了使用ES6生成器执行异步JavaScript的示例。但是,这只是为了演示,而且很可能您不想使用这种技术。用ES7 (试验性的)对ES5跟踪器(如Babel或TypeScript )使用异步/等待。

代码语言:javascript
复制
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);
  });
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27236960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档