首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在JavaScript中实现协同控制流程

在JavaScript中实现协同控制流程
EN

Stack Overflow用户
提问于 2017-04-21 16:21:22
回答 2查看 567关注 0票数 0

下面实现了一个控制流包装器co,使异步代码只能由yield关键字来描述。

这基本上是async/await在ESwhatever的引擎盖下所做的吗?

代码语言:javascript
运行
复制
co(function*() {
    console.log('...');
    yield one();
    console.log('...');
    yield two();
})


function co(gFn) {
    var g = gFn();

    return Promise.resolve()
        .then(go);

    function go() {        
        var result = g.next();
        if(result.done) {
            return;
        }
        if(isPromise(result.value)) {
            return result.value.then(go); // Promises block until resolution.
        }
        return Promise.resolve(result);
    }    
}

function isPromise(o) {
    return o instanceof Promise;
}

function one() {
    return new Promise(resolve => setTimeout(() => (console.log('one'), resolve()), 1000));
}

function two() {
    return new Promise(resolve => setTimeout(() => (console.log('two'), resolve()), 1000));
}

编辑:

根据我为考虑返回值而更新的答复:

代码语言:javascript
运行
复制
co(function*() {
    console.log('...');
    const result1 = yield one();
    console.log('result1: ', result1);
    const result2 = yield two();
    console.log('result2: ', result2);
    const result3 = yield[one(), two()];
    console.log('result3: ', result3);
    const result4 = yield{
        one: one(),
        two: two()
    };
    console.log('result4: ', result4);
})

function co(gFn) {
    var g = gFn();

    return Promise.resolve().then(go);

    function go() {
        var result = g.next(...arguments);
        if (isPromise(result.value)) {
            return result.value.then(go);
        }
        if (Array.isArray(result.value)) {
            return Promise.all(result.value).then(go);
        }
        if (isObject(result.value)) {
            var o = {};
            var promises = Object.keys(result.value).map(k=>result.value[k].then(r=>o[k] = r));
            return Promise.all(promises).then(()=>o).then(go);
        }
        return Promise.resolve(result);
    }
}

function isPromise(o) {
    return o instanceof Promise;
}

function isObject(val) {
    return val && (Object === val.constructor);
}

function one() {
    return new Promise(resolve=>setTimeout(()=>(console.log('one'),
    resolve('result 1')), 1000));
}

function two() {
    return new Promise(resolve=>setTimeout(()=>(console.log('two'),
    resolve('result 2')), 1000));
}

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-21 16:29:20

这基本上是ESwhatever中异步/等待在幕后所做的吗?

不怎么有意思。这是一种不同的方法来做同样的事情。async/await变成的更像是

代码语言:javascript
运行
复制
async function foo() {
  const bar = await Bar();
  bar++;
  const baz = await Baz(bar);
  return baz;
}

变成了

代码语言:javascript
运行
复制
function foo() {
  return Bar()
    .then(bar => {
      bar++;
      return Baz(bar)
        .then(baz => {
          return baz;
        });
    });
}
票数 5
EN

Stack Overflow用户

发布于 2017-04-21 16:34:05

第三阶段草案/2016年1月26日异步函数提供了三种模式的示例:PromiseGeneratorAsync Functions;其中不同的方法基本上产生相同的结果。

Examples# 以下面的例子为例,首先使用承诺编写。此代码将元素上的一组动画链接起来,在动画中出现异常时停止,并返回最终成功执行的动画产生的值。 函数chainAnimationsPromise(elem,动画){ let ret = null;let p= currentPromise;for(const anim of动画){p=p.then(函数(Val){ ret = val;}) }返回p.catch(函数(E){ /*忽略并继续前进*/ }).then(函数()););} 已经有了承诺,代码已经从直接回调风格中得到了很大的改进,这种循环和异常处理是很有挑战性的。 Task.js和类似的库提供了一种方法来使用生成器来进一步简化代码,保持相同的含义: 函数chainAnimationsGenerator(elem,动画){返回子程序(函数*()){ let ret = null;尝试{ for(const anim of动画){ ret =产生anim(elem);} /* (E){/*忽略并继续返回ret;};} 这是一个显著的进步。所有超出代码语义内容的承诺样板都被删除,内部函数的主体表示用户意图。但是,还有一个外层的样板可以将代码包装在一个额外的生成器函数中,并将其传递给库以转换为承诺。这一层需要在使用此机制产生承诺的每个功能中重复。这在典型的异步Javascript代码中是如此常见,因此消除对剩余样板的需求是有价值的。 使用异步函数,将删除所有剩余的样板,只在程序文本中留下语义上有意义的代码: 异步函数chainAnimationsAsync(elem,动画){ let ret = null;尝试{ for(const of动画){ ret =等待anim(elem);} /* (E){/*忽略并继续返回ret;}

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43547606

复制
相关文章

相似问题

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