为什么这两种方法都不能实现异步调用(一个使用承诺,另一个使用生成器)产生相同的结果?

时间:2022-02-23 01:08:13

I have a small node script that fetches users from Github using node-fetch (window.fetch compatible API on Node.js runtime). I then console.log the users, as can be seen below, using the returned Promise from fetch:

我有一个小节点脚本,它使用node-fetch(窗口)从Github获取用户。在节点上获取兼容的API。js运行时)。然后我控制台。使用fetch返回的承诺记录用户,如下所示:

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));

The above works perfectly.

上述工作完美。

I now want to do the same thing using a generator together with the promise:

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

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)
);

This version does not work. The output is:

这个版本不工作。的输出是:

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

Why aren't these two code snippets producing the same result?

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

Note: this is what my package.json looks like:

注:这是我的包裹。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"
  }
}

1 个解决方案

#1


2  

Older Node version is likely used in the example. Current Node versions (6 and higher) have promise implementation that handles unhandled rejections by default, this provides feedback on error handling and eases debugging a lot (that's the reason why unhandled rejection handling was introduced).

示例中可能使用旧的节点版本。当前的节点版本(6或更高版本)有承诺实现,默认情况下可以处理未处理的拒绝,这提供了错误处理的反馈,并简化了调试(这就是为什么引入了未处理的拒绝处理)。

Then the output would look like

那么输出会是这样的

initial response is Promise { }

初始响应是Promise {}

Response in generator is Promise { }

生成器中的响应是Promise {}

(node:12364) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: body used already for: https://api.github.com/users?since=0

(节点:12364)unhandledmederejectionwarning:未经处理的承诺拒绝(拒绝id: 2): Error: body used for: https://api.github.com/users?

And this indicates the problem. Calling response.json() twice results in error, and response.json() returns a promise (errors from which weren't caught).

这就是问题所在。json()两次导致错误,并且response.json()返回一个承诺(未被捕获的错误)。

Instead it should be

相反,它应该

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)
})

It should be noticed that it is a good exercise to study generators, but for practical use co is widely known for implementing this approach.

应该注意的是,研究发电机是一个很好的练习,但是对于实际应用来说,co是众所周知的执行这种方法。

#1


2  

Older Node version is likely used in the example. Current Node versions (6 and higher) have promise implementation that handles unhandled rejections by default, this provides feedback on error handling and eases debugging a lot (that's the reason why unhandled rejection handling was introduced).

示例中可能使用旧的节点版本。当前的节点版本(6或更高版本)有承诺实现,默认情况下可以处理未处理的拒绝,这提供了错误处理的反馈,并简化了调试(这就是为什么引入了未处理的拒绝处理)。

Then the output would look like

那么输出会是这样的

initial response is Promise { }

初始响应是Promise {}

Response in generator is Promise { }

生成器中的响应是Promise {}

(node:12364) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: body used already for: https://api.github.com/users?since=0

(节点:12364)unhandledmederejectionwarning:未经处理的承诺拒绝(拒绝id: 2): Error: body used for: https://api.github.com/users?

And this indicates the problem. Calling response.json() twice results in error, and response.json() returns a promise (errors from which weren't caught).

这就是问题所在。json()两次导致错误,并且response.json()返回一个承诺(未被捕获的错误)。

Instead it should be

相反,它应该

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)
})

It should be noticed that it is a good exercise to study generators, but for practical use co is widely known for implementing this approach.

应该注意的是,研究发电机是一个很好的练习,但是对于实际应用来说,co是众所周知的执行这种方法。