你好!
我有一个在开发/浏览器中完美运行的@rest
graphql 查询,但是当我在服务器(SSR)上运行相同的代码时,它会失败并显示一条长长的神秘错误消息。
(如果我禁用@rest
指令,其他一切都可以在浏览器和 SSR 中完美运行)。
堆栈跟踪:
(node:26034) UnhandledPromiseRejectionWarning: Error: Network error: current.forEach is not a function
at new ApolloError (.../demo-component/node_modules/src/errors/ApolloError.ts:56:5)
at .../demo-component/node_modules/src/core/QueryManager.ts:512:31
at .../demo-component/node_modules/src/core/QueryManager.ts:1046:11
at Array.forEach (<anonymous>)
at .../demo-component/node_modules/src/core/QueryManager.ts:1045:10
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (.../demo-component/node_modules/src/core/QueryManager.ts:1039:18)
at .../demo-component/node_modules/src/core/QueryManager.ts:411:18
(node:26034) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)
(node:26034) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
请指教 :/
再深入一点,我只是想在 NodeJS 中执行查询,而不用担心 SSR 等,
并有这个代码:
client
.query({query: Site, variables: {domain: "demo.example.com"}})
.then(
() => console.log("Fullfilled"),
({graphQLErrors, networkError, message, extraInfo}) =>
console.error("Rejected", graphQLErrors, networkError, message,extraInfo)
)
有了这个结果:
Rejected [] TypeError: current.forEach is not a function
at /home/richard/Projects/skil/demo-component/node_modules/src/restLink.ts:671:13
at Array.reduce (<anonymous>)
at concatHeadersMergePolicy (/home/richard/Projects/skil/demo-component/node_modules/src/restLink.ts:664:23)
at RestLink.request (/home/richard/Projects/skil/demo-component/node_modules/src/restLink.ts:1235:21)
at ApolloLink.request (/home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:76:19)
at /home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:78:26
at ApolloLink.request (/home/richard/Projects/skil/demo-component/node_modules/src/ApolloClient.ts:139:16)
at ApolloLink.request (/home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:76:19)
at /home/richard/Projects/skil/demo-component/node_modules/apollo-link/src/link.ts:78:26
at DedupLink.request (/home/richard/Projects/skil/demo-component/node_modules/apollo-link-dedup/src/dedupLink.ts:39:30) Network error: current.forEach is not a function undefined
restLink.ts:671
是这段代码:
export const concatHeadersMergePolicy: RestLink.HeadersMergePolicy = (
...headerGroups: Headers[]
): Headers => {
return headerGroups.reduce((accumulator, current) => {
if (!current) {
return accumulator;
}
if (!current.forEach) {
current = normalizeHeaders(current);
}
current.forEach((value, key) => { // <-- This line here
accumulator.append(key, value);
});
return accumulator;
}, new Headers());
};
https://github.com/apollographql/apollo-link-rest/blob/master/src/restLink.ts#L671
另外,如果我用这个替换失败的forEach
:
Object.keys(current).forEach(key => {
accumulator.append(key, current[key])
})
一切都恢复正常...
挑战,我不明白上面几行的目的:
if (!current.forEach) {
current = normalizeHeaders(current);
}
因为这总是会失败,并且总是执行normalizeHeaders()
?
我将在这里冒险并猜测 Node 对new Headers()
的使用感到不安。 一个新的 Headers 实例在其原型上有一个forEach
方法。 如果提供给 reduce 的对象缺少 forEach 方法,我们执行normalizeHeaders
。 这确定变量是否是 Headers 的实例。 如果没有,它将再次使用new Headers()
生成一组新的标头,从而导致您在此处看到的问题。
您的Object.keys(current).forEach()
示例正在运行,因为它成功地将普通对象转换为数组,允许您对其调用.forEach()
。
下一步调试明智... normalizeHeaders()
在您的 SSR 应用程序中的结果是什么? 看看它输出了什么,我猜你会发现它是一个普通的对象,而不是 Headers 的一个实例。
据我所知,我不相信 SSR 已经过全面测试(参见 #155),但@fbartho可能会对此有所了解。
SSR 目前不是直接测试或支持的功能。 理由:如果你有 SSR,你可以部署你自己的 Apollo GraphQL 服务器,并且你不需要 link-rest
然而,有些人已经想通了。 我并不反对改善那里世界状况的 PR。 在我看来,我们可能只需要一个 SSR 教程。
此外,根据您的运行时环境,需要对标头进行 polyfill 是相对常见的。 你试过了吗? @理查德87
@tombarton 的响应是正确的:该代码的目的是将标头哈希转换为适当的 Headers 类。
大家好!
感谢您对我的问题的关注;)
我的index.js
的底部是这样的:
if (global.Headers == null) {
global.Headers = require("fetch-headers");
}
// Set up babel to do its thing... env for the latest toys, react-app for CRA
// Notice three plugins: the first two allow us to use import rather than require, the third is for code splitting
// Polyfill is required for Babel 7, polyfill includes a custom regenerator runtime and core-js
require('@babel/polyfill');
require('@babel/register')({
ignore: [/\/(build|node_modules)\//],
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-transform-instanceof',
]
});
// Now that the nonsense is over... load up the server entry point
require('./server');
所以我很确定我有 Header polyfill(也没有global.Headers
我还有很多其他问题)......
我已经在我的 PHP 应用程序(API-Platform + https://webonyx.github.io/graphql-php/)中紧密集成了一个运行的 GraphQL 服务器,所以我不想安装额外的 Apollo GraphQL 服务器,我只想更快地加载 React 应用程序:D
我很难调试 restLink.ts,但我已经投入了一些战略性的console.log
但它current
_似乎是一个计划对象,但console.log
可能会错过一些信息...
export const concatHeadersMergePolicy: RestLink.HeadersMergePolicy = (
...headerGroups: Headers[]
): Headers => {
return headerGroups.reduce((accumulator, current) => {
if (!current) {
return accumulator;
}
console.log(current.constructor.name)
if (!current.forEach) {
current = normalizeHeaders(current);
}
console.log(current.constructor.name)
Object.keys(current).forEach(key => {
accumulator.append(key, current[key])
})
return accumulator;
}, new Headers());
};
打印出“标题”两次...
console.log(current.forEach)
无论如何都会打印出 Undefined ,看来我的 Headers polyfill 没有forEach
属性?
我的 PHPStorm 告诉我headers
有一个 forEach 方法,但是在节点中运行此代码时,我得到一个headers.forEach is not a function
:
const Headers = require("fetch-headers");
const headers = new Headers();
console.log(headers)
console.log(headers.forEach)
console.log(!headers.forEach)
headers.forEach(h => console.log(h))
输出:
node /home/richard/Projects/demo-component/src/test.js
Headers {}
undefined
true
/home/richard/Projects/demo-component/src/test.js:10
headers.forEach(h => console.log(h))
^
TypeError: headers.forEach is not a function
at Object.<anonymous> (/home/richard/Projects/demo-component/src/test.js:10:9)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
at startup (internal/bootstrap/node.js:285:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:739:3)
在我的引导文件中添加这个解决了我所有的问题:D
if (global.Headers == null) {
const fetch = require('node-fetch');
global.Headers = fetch.Headers;
}
注意使用node-fetch
而不是fetch-headers
解决了这个问题!
最有用的评论
在我的引导文件中添加这个解决了我所有的问题:D
注意使用
node-fetch
而不是fetch-headers
解决了这个问题!