为什么这两种asynchronous调用方式(一种使用承诺,另一种是生成器)产生相同的结果?

我有一个小节点脚本,使用Node-fetch(Node.js运行时的window.fetch兼容API)从Github中获取用户。 然后我console.log用户,如下所示,使用从提取返回的承诺:

import fetch from 'node-fetch'; import "babel-polyfill"; const fetchUsers = lastReceivedId => fetch(`https://api.github.com/users?since=${lastReceivedId}`); console.log("Promise-based:"); fetchUsers(0) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); 

以上作品完美。

我现在想用一个发电机和承诺一起做同样的事情:

 import fetch from 'node-fetch'; import "babel-polyfill"; const fetchUsers = lastReceivedId => fetch(`https://api.github.com/users?since=${lastReceivedId}`); function* main() { try { const res = yield fetchUsers(0); console.log("Response in generator is ", res); } catch (err) { console.log(err); } } console.log("Generator-Promise-based:") const it = main(); const p = it.next().value; p.then( function(response) { console.log("initial response is ", response.json()) it.next(response.json()) }, err => it.throw(err) ); 

此版本不起作用。 输出是:

 Generator-Promise-based: initial response is Promise {} Response in generator is Promise {} 

为什么不是这两个代码片段产生相同的结果?

注意:这是我的package.json的样子:

 { "name": "NodePractice", "version": "1.0.0", "description": "", "main": "generators.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "babel src --watch -d lib" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.24.1", "babel-preset-es2015": "^6.24.1" }, "dependencies": { "babel-polyfill": "^6.23.0", "node-fetch": "^1.6.3" } } 

较旧的节点版本可能在该示例中使用。 当前的Node版本(6和更高版本)有承诺实现,默认处理未处理的拒绝,这提供了error handling的反馈,并简化了很多debugging(这就是为什么引入了未处理的拒绝处理的原因)。

那么输出结果就像

最初的回应是Promise {}

生成器中的响应是Promise {}

(节点:12364)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝标识:2):错误:正文已经用于: https ://api.github.com/users?since =0

这表明了这个问题。 调用response.json()两次会导致错误,并且response.json()返回一个promise(没有被捕获的错误)。

相反它应该是

 const it = main(); const p = it.next().value; p .then(response => { const jsonPromise = response.json(); console.log("json promise is ", jsonPromise); return jsonPromise; }) .then(json => { console.log("initial response is ", json); it.next(json); }) .catch(err => { console.error('error', err); it.throw(err) }) 

应该注意的是,研究发电机组是一个很好的练习,但实际使用co是众所周知的实施这种方法。