08月18, 2016

【译】ES7 异步函数

原文:http://www.zcfy.cc/article/247

ES7 异步函数

发表于2014年3月27

  • 呐,这并不是个渐进增强的文章

异步函数灰常完美!我爱它。

Promises异步编程

HTML5Rocks关于promises的文章中,最后一个例子展示了如何加载小说中的JSON数据,然后将其中的章节抓取出来并且按顺序渲染。

代码如下:

function loadStory() {
  return getJSON("story.json").then(function(story) {
    addHtmlToPage(story.heading);

    return story.chapterURLs.map(getJSON)
      .reduce(function(chain, chapterPromise) {
        return chain.then(function() {
          return chapterPromise;
        }).then(function(chapter) {
          addHtmlToPage(chapter.html);
        });
      }, Promise.resolve());
  }).then(function() {
    addTextToPage("All done");
  }).catch(function(err) {
    addTextToPage("Argh, broken: " + err.message);
  }).then(function() {
    document.querySelector(".spinner").style.display = "none";
  });
}

还不错,然而……

这次我们用ES7异步函数试试…

async function loadStory() {
  try {
    let story = await getJSON("story.json");
    addHtmlToPage(story.heading);
    for (let chapter of story.chapterURLs.map(getJSON)) {
      addHtmlToPage((await chapter).html);
    }
    addTextToPage("All done");
  } catch (err) {
    addTextToPage("Argh, broken: " + err.message);
  }
  document.querySelector(".spinner").style.display = "none";
}

用异步函数(full proposal),你可以等待promise进行处理,它会以非阻塞的方式中断函数,如果promise成功(resolve)就返回value。如果promise失败,则抛出失败,然后在catch中进行捕获。

Edit:我第一次使用await是在一个箭头函数中,显然这是不允许的,因此我改用了一个for循环。Domenic在why await can't be used in arrow functions中纠正了我这个愚蠢的错误。

loadStory函数返回了一个promise,因此你可以继续用它调用其他异步函数。

(async function() {
  await loadStory();
  console.log("Yey, story successfully loaded!");
}());

直到ES7发布…

如今你可以通过Traceur transpiler来使用异步函数和其他ES6/7特性。当然,你也可以通过ES6生成器来创建类似异步函数的功能。

你需要一点库代码,a spawn function。然后你可以用生成器去模仿异步函数了。

function loadStory() {
  return spawn(function *() {
    try {
      let story = yield getJSON("story.json");
      addHtmlToPage(story.heading);
      for (let chapter of story.chapterURLs.map(getJSON)) {
        addHtmlToPage((yield chapter).html));
      }
      addTextToPage("All done");
    } catch (err) {
      addTextToPage("Argh, broken: " + err.message);
    }
    document.querySelector(".spinner").style.display = "none";
  });
}

在上面我给出了一个生成器函数spawn,通过function *()你可以分辨出这个一个生成器,spawn函数在生成器中调用了.next(),它收到promise在yield中的调用,并且当返回成功(resolve)时调用.next(),返回失败(reject)时调用.throw()抛出错误。

ES7将spwan函数制定入规范并且使其更易用。能够用标准的方法简化异步编程真是太棒了!

延伸阅读

译者有话说

第一次尝试把一篇文章翻译出来,一边翻译一边学习,火候不够,所以各位大大看到哪里翻译的不好求指点QAQ

英文原文:https://jakearchibald.com/2014/es7-async-functions/

本文链接:http://crystalmiao.com/post/es7-async-functions.html

-- EOF --

Comments