promise 和生成器允许您编写异步代码.我不明白为什么ECMA脚本6中引入了这两种机制.什么时候最好使用promise ,什么时候使用发电机?

推荐答案

这两种技术之间没有对立:它们共存,相辅相成.

Promises allows you to get the result of an asynchronous operation which is not available yet.
It solves the Pyramid of Doom problem. So instead of:

function ourImportantFunction(callback) {
  //... some code 1
  task1(function(val1) {
    //... some code 2
    task2(val1, function(val2) {
      //... some code 3
      task3(val2, callback);
    });
  });
}

你可以写:

function ourImportantFunction() {
  return Promise.resolve()
    .then(function() {
        //... some code 1
        return task1(val3)
    })
    .then(function(val2) {
        //... some code 2
        return task2(val2)
    })
    .then(function(val2) {
        //... some code 3
        return task3(val2);
    });
}

ourImportantFunction().then(callback);

But even with promises you must write code in asynchronous fashion - you must always pass callbacks to the functions.
Writing asynchronous code is much harder than synchronous. Even with promises, when the code is huge, it becomes difficult to see the algorithm (it's very subjective, but for the majority of programmers I think it's true).

So we want to write asynchronous code in synchronous fashion. That's where generators are coming to help us.
Instead of the code above 你可以写:

var ourImportantFunction = spawn(function*() {
    //... some code 1
    var val1 = yield task1();
    //... some code 2
    var val2 = yield task2(val1);
    //... some code 3
    var val3 = yield task3(val2);

    return val3;
});

ourImportantFunction().then(callback);

其中最简单的可能spawn实现可以是:

function spawn(generator) {
  return function() {    
    var iter = generator.apply(this, arguments);

    return Promise.resolve().then(function onValue(lastValue){
      var result = iter.next(lastValue); 

      var done  = result.done;
      var value = result.value;

      if (done) return value; // generator done, resolve promise
      return Promise.resolve(value).then(onValue, iter.throw.bind(iter)); // repeat
    });
  };
}

正如您所见,value(一些异步函数task{N}的结果)一定是一个promise .你不能用回调来做这件事.

剩下要做的是将spawn技术实现到语言本身中.所以我们用async代替spawn,用await代替yield,现在是ES7 async/await:

var ourImportantFunction = async function() {
    //... some code 1
    var val1 = await task1();
    //... some code 2
    var val2 = await task2(val1);
    //... some code 3
    var val3 = await task3(val2);

    return val3;
}

I recommend you to watch this video to understand more this and some other coming techniques.
Hint: If the guy speaks too fast for you, slow down the speed of playing ("settings" in right bottom corner, or just push [shift + <])

What is the best: only callbacks, or promises, or promises with generators - this is a very subjective question.
Callbacks is the fastest solution possible at this time (performance of native promises are very bad now). Promises with generators give you opportunity to write asynchronous code in synchronous fashion. But for now they are much slower than simple callbacks.

Node.js相关问答推荐

需要关于基于角色授权的设计建议

仅当所需文档是最后一个文档时才更新MongoDB,否则插入

使用 playwright 获取页面中同一 url 的所有响应

如何在套接字对象中存储或添加数据?

express 和 mongoose 的新密码不正确

无法使用 node 预签名 url 从 React 将图像文件上传到 s3

为什么我的 Cypress Post 请求的请求正文是空的?

node Axios 创建全局令牌变量以在单独的变量头中使用

一个非常奇怪的JavaScript heap out of memory问题

如何在 TypeScript 中输出 Hackerrank 二叉树问题?

为什么需要在 NodeJS 应用程序中创建服务器?

突然 React 无法执行create-react-app命令.为什么会发生这种情况,我该如何解决?

NodeJs 过滤掉目录异步

yarn.lock 和 npm 的 package-lock 有什么区别?

npm 不会安装 express 吗?

ISODate 未定义

NODEJS 进程信息

使用 pm2 编程 api 重命名进程

如何判断 Node.js 中是否设置了环境变量?

将 expressjs 绑定到特定的 IP 地址