在 node.js 中编译代码时出现此错误,我该如何解决?
ReferenceError:未定义提取
https://i.stack.imgur.com/3Syvz.png
这是我正在做的功能,它负责从特定的电影数据库中恢复信息。
function getMovieTitles(substr){
pageNumber=1;
let url = 'https://jsonmock.hackerrank.com/api/movies/search/?Title=' + substr + "&page=" + pageNumber;
fetch(url).then((resp) => resp.json()).then(function(data) {
let movies = data.data;
let totPages = data.total_pages;
let sortArray = [];
for(let i=0; i<movies.length;i++){
sortArray.push(data.data[i].Title);
}
for(let i=2; i<=totPages; i++){
let newPage = i;
let url1 = 'https://jsonmock.hackerrank.com/api/movies/search/?Title=' + substr + "&page=" + newPage;
fetch(url1).then(function(response) {
var contentType = response.headers.get("content-type");
if(contentType && contentType.indexOf("application/json") !== -1) {
return response.json().then(function(json) {
//console.log(json); //uncomment this console.log to see the JSON data.
for(let i=0; i<json.data.length;i++){
sortArray.push(json.data[i].Title);
}
if(i==totPages)console.log(sortArray.sort());
});
} else {
console.log("Oops, we haven't got JSON!");
}
});
}
})
.catch(function(error) {
console.log(error);
});
}
fetch
不是标准的 nodejs 方法 - 您需要 node-fetch
fetch()
是为浏览器设计的,然后在您显然缺少的第三方模块中反向移植到 node.js。 request()
或 request-promise()
库更原生地为 node.js 构建,并支持更广泛的 node.js 选项,包括流、无数的身份验证方法等......
fetch API 未在 Node.js 中实现。
为此,您需要使用外部模块,例如 node-fetch。
像这样在你的 Node 应用程序中安装它
npm install node-fetch
然后将下面的行放在您使用 fetch API 的文件的顶部:
import fetch from "node-fetch";
这是一个快速的脏修复,请尝试在生产代码中消除这种用法。
如果必须在全局范围内访问 fetch
import fetch from 'node-fetch'
globalThis.fetch = fetch
fetch
返回的承诺并自动完成可用方法的唯一方法。同意在生产中应该避免它,但对本地开发非常有帮助!
const nodeFetch = require('node-fetch') as typeof fetch;
您可以使用 @lquixada 中的 cross-fetch
平台无关:浏览器、节点或 react native
安装
npm install --save cross-fetch
用法
承诺:
import fetch from 'cross-fetch';
// Or just: import 'cross-fetch/polyfill';
fetch('//api.github.com/users/lquixada')
.then(res => {
if (res.status >= 400) {
throw new Error("Bad response from server");
}
return res.json();
})
.then(user => {
console.log(user);
})
.catch(err => {
console.error(err);
});
使用异步/等待:
import fetch from 'cross-fetch';
// Or just: import 'cross-fetch/polyfill';
(async () => {
try {
const res = await fetch('//api.github.com/users/lquixada');
if (res.status >= 400) {
throw new Error("Bad response from server");
}
const user = await res.json();
console.log(user);
} catch (err) {
console.error(err);
}
})();
amazon-cognito-identity-js
接收 ReferenceError: fetch is not defined
错误。
如果你想避免 npm install 并且不在浏览器中运行,你也可以使用 nodejs https 模块;
const https = require('https')
const url = "https://jsonmock.hackerrank.com/api/movies";
https.get(url, res => {
let data = '';
res.on('data', chunk => {
data += chunk;
});
res.on('end', () => {
data = JSON.parse(data);
console.log(data);
})
}).on('error', err => {
console.log(err.message);
})
.end()
以实际启动请求。请参阅docs
您应该在文件中添加此导入:
import * as fetch from 'node-fetch';
然后,运行此代码以添加 node-fetch
:
$ yarn add node-fetch
如果您使用的是 typescript,请安装 node-fetch 类型:
$ yarn add @types/node-fetch
TS2349: This expression is not callable. Type 'typeof import("/node_modules/@types/node-fetch/index")' has no call signatures.
。它仅适用于 require
。
$ yarn add @types/node-fetch
以安装节点获取类型
import
与 require
。似乎 node-fetch
不支持这种现代导入语法。
Node.js 尚未实现 fetch() 方法,但您可以使用这个奇妙的 JavaScript 执行环境的外部模块之一。
在其他答案之一中,引用了“node-fetch”,这是一个不错的选择。
在您的项目文件夹(您拥有 .js 脚本的目录)中,使用以下命令安装该模块:
npm i node-fetch --save
然后将它用作要使用 Node.js 执行的脚本中的常量,如下所示:
const fetch = require("node-fetch");
已编辑 - 新解决方案
要使用最新版本 (3.0.0),您必须像这样进行导入:
const fetch = (url) => import('node-fetch').then(({default: fetch}) => fetch(url));
老回答者:
这可能不是最好的解决方案,但如果您安装此版本:
npm install node-fetch@1.7.3
您现在可以使用下面的行而不会出错。
const fetch = require("node-fetch");
require
,请使用将获得关键更新的版本 2:“如果您无法切换到 ESM,请使用与 CommonJS 保持兼容的 v2。将继续为 v2 发布关键错误修复。” node-fetch@2
您必须将 isomorphic-fetch
模块用于您的 Node
项目,因为 Node
尚不包含 Fetch API
。要解决此问题,请运行以下命令:
npm install --save isomorphic-fetch es6-promise
安装后在您的项目中使用以下代码:
import "isomorphic-fetch"
import 'cross-fetch/polyfill';
以平滑测试环境的粗糙边缘。
fetch
在实验标志 --experimental-fetch
下来到 Node v17
它将在没有标志的 Node v18 中可用。
https://github.com/nodejs/node/pull/41749#issue-1118239565
您不再需要安装任何其他软件包
最好的一个是用于获取的 Axios 库。使用 npm i --save axios
进行安装并像 fetch 一样使用它,只需编写 axios 而不是 fetch 然后在 then() 中获取响应。
对于那些也在 node-js 上使用 typescript 并遇到 ReferenceError: fetch is not defined
错误的用户
npm install
这些软件包:
"amazon-cognito-identity-js": "3.0.11"
"node-fetch": "^2.3.0"
然后包括:
import Global = NodeJS.Global;
export interface GlobalWithCognitoFix extends Global {
fetch: any
}
declare const global: GlobalWithCognitoFix;
global.fetch = require('node-fetch');
amazon-cognito-identity-js
与此问题无关,无需安装即可解决此错误。它也与打字稿无关。
对于 CORS 请求,似乎使用“http”或“https”获取支持 URL 方案。
安装节点获取库 npm install node-fetch
,读取文件并解析为 json。
const fs = require('fs')
const readJson = filename => {
return new Promise((resolve, reject) => {
if (filename.toLowerCase().endsWith(".json")) {
fs.readFile(filename, (err, data) => {
if (err) {
reject(err)
return
}
resolve(JSON.parse(data))
})
}
else {
reject(new Error("Invalid filetype, <*.json> required."))
return
}
})
}
// usage
const filename = "../data.json"
readJson(filename).then(data => console.log(data)).catch(err => console.log(err.message))
在 node.js 中,您可以使用:node-fetch 包
npm i node-fetch
然后 :
import fetch from 'node-fetch';
这是(nodejs)中的完整示例:
import fetch from "node-fetch";
const fetchData = async () => {
const res = await fetch("https://restcountries.eu/rest/v2/alpha/col"); // fetch() returns a promise, so we need to wait for it
const country = await res.json(); // res is now only an HTTP response, so we need to call res.json()
console.log(country); // Columbia's data will be logged to the dev console
};
fetchData();
在 HackerRank 中,有些库是默认安装的,有些则没有。
因为它运行的是 Node.js,默认情况下不安装 fetch API。
您最好的办法是检查库是否已安装。
在练习的顶部,有以下内容:
const https = require('https');
请尝试将其添加到顶部:
const axios = require('axios');
然后运行代码。
如果出现编译错误,则不可用,否则可以使用axios
,它是fetch
的一个很好的替代品
要将其与 then
一起使用,您可以:
function getMovieTitles(substr){
axios.get(url)
.then(function(response){
console.log(response.data);
})
}
或利用 async/await
async function getMovieTitles(substr){
let response = await axios.get(url)
console.log(response.data);
}
以下在 Node.js 12.x 中适用于我:
npm i node-fetch;
初始化 Dropbox 实例:
var Dropbox = require("dropbox").Dropbox;
var dbx = new Dropbox({
accessToken: <your access token>,
fetch: require("node-fetch")
});
例如上传内容(在这种情况下使用的异步方法):
await dbx.filesUpload({
contents: <your content>,
path: <file path>
});
对我来说,这些看起来更简单。
npm install node-fetch
import fetch from "node-fetch";
实际上有很多不同的库可以让 fetch
在浏览器中可用。
我知道的主要有:
节点获取
交叉获取
whatwg获取
同构提取
我目前使用 node-fetch,它运行良好,但我真的不知道哪个是“最好的”。 (尽管我链接的 openbase.com 页面提供了一些有关使用情况的元数据 [例如,Github 明星、npm 下载],这可以提供帮助)
这个答案不直接回答这个问题。相反,它建议另一种选择。
为什么?因为使用 'node-fetch' 变得越来越复杂,因为您无法使用 const fetch = require('node-fetch')
导入更新的版本。你必须做更多的事情才能让它发挥作用。
尝试使用 axios 包:
用于获取的简单安装 npm i axios 代码就像
const response = await axios.get(url).then(res => res.data)
这对我有用:
const nodeFetch = require('node-fetch') as typeof fetch;
解决方案 2022 年 7 月,节点版本 18.4.0
fetch
仍处于试验阶段,但我为您准备了一个分步指南。您不必额外安装任何东西。
第 1 步:假设我们想要获取多个 URL
我使用标准的开放 API(星球大战 API):
const starWarsPeople = [
'https://swapi.dev/api/people/1/',
'https://swapi.dev/api/people/2/',
'https://swapi.dev/api/people/3/',
];
第 2 步:我们创建一个普通的自定义异步迭代器:
这不是必需的,但我们想这样做,因为这样每一步都在我们的控制之中:
starWarsPeople[Symbol.asyncIterator] = () => {
let index = 0;
return {
async next() {
if (index === starWarsPeople.length) {
return { done: true };
}
const url = starWarsPeople[index];
index++;
const response = await fetch(url);
if (!response.ok) {
throw new Error('Cannot retrieve Url: ' + url);
}
return {
value: await response.json(),
done: false,
};
},
};
};
第 3 步:我们使用 IIFE(立即调用函数表达式)
请注意最后一行中的 ()
。
(async function () {
try {
for await (const person of starWarsPeople) {
console.log('Person: ', person?.name);
}
} catch (err) {
console.error('Error: ', err);
}
})();
最后但最不重要的:the whole example online (StackBlitz)
这是你的`tsconfig.json`
{
"compilerOptions": {
"target": "esnext",
"lib": ["ESNext", "DOM"],
"module": "esnext",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true
}
}
只需将您的 app.js 文件扩展名设置为 app.mjs 即可解决问题!!!:)
听起来可能很傻,但我只是在错误的项目中调用了 npm i node-fetch --save
。确保您位于正确的目录中。
--save
仅用于测试的内容。请改用 --save-dev
。
如果需要安装:
npm install --save global-fetch
然后
var fetch = require("node-fetch");
global-fetch
还是 node-fetch
?
不定期副业成功案例分享
.mjs
保存我的文件才能使其正常工作。