Node.js异步函数未处理Promise拒绝错误求助
MintyTON项目运行
yarn start出现ERR_UNHANDLED_REJECTION错误排查 问题描述
运行MintyTON项目的yarn start命令时触发ERR_UNHANDLED_REJECTION错误,提示异步函数未设置catch块或Promise未通过.catch()处理。
运行日志
MintyTON % yarn start yarn run v1.22.19 $ tsc --skipLibCheck && node dist/app.js Started uploading images to IPFS... node:internal/process/promises:289 triggerUncaughtException(err, true /* fromPromise */); ^ [UnhandledPromiseRejection: 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(). The promise rejected with the reason "#".] { code: 'ERR_UNHANDLED_REJECTION' } Node.js v20.5.1 error Command failed with exit code 1.
相关代码(app.ts)
import * as dotenv from "dotenv"; import { toNano } from "ton-core"; import { readdir } from "fs/promises"; import { openWallet } from "./utils"; import { waitSeqno } from "./delay"; import { NftCollection } from "./contracts/NftCollection"; import { NftItem } from "./contracts/NftItem"; import { updateMetadataFiles, uploadFolderToIPFS } from "./metadata"; import { GetGemsSaleData, NftSale } from "./contracts/NftSale"; import { NftMarketplace } from "./contracts/NftMarketplace"; dotenv.config(); async function init() { const metadataFolderPath = "./data/metadata/"; const imagesFolderPath = "./data/images/"; const wallet = await openWallet(process.env.MNEMONIC!.split(" "), true); console.log("Started uploading images to IPFS..."); const imagesIpfsHash = await uploadFolderToIPFS(imagesFolderPath); console.log( `Successfully uploaded the pictures to ipfs: https://gateway.pinata.cloud/ipfs/${imagesIpfsHash}` ); console.log("Started uploading metadata files to IPFS..."); await updateMetadataFiles(metadataFolderPath, imagesIpfsHash); const metadataIpfsHash = await uploadFolderToIPFS(metadataFolderPath); console.log( `Successfully uploaded the metadata to ipfs: https://gateway.pinata.cloud/ipfs/${metadataIpfsHash}` ); console.log("Start deploy of nft collection..."); const collectionData = { ownerAddress: wallet.contract.address, royaltyPercent: 0.05, // 0.05 = 5% royaltyAddress: wallet.contract.address, nextItemIndex: 0, collectionContentUrl: `ipfs://${metadataIpfsHash}/collection.json`, commonContentUrl: `ipfs://${metadataIpfsHash}/`, }; const collection = new NftCollection(collectionData); let seqno = await collection.deploy(wallet); console.log(`Collection deployed: ${collection.address}`); await waitSeqno(seqno, wallet); // Deploy nft items const files = await readdir(metadataFolderPath); files.pop(); let index = 0; seqno = await collection.topUpBalance(wallet, files.length); await waitSeqno(seqno, wallet); console.log(`Balance top-upped`); for (const file of files) { console.log(`Start deploy of ${index + 1} NFT`); const mintParams = { queryId: 0, itemOwnerAddress: wallet.contract.address, itemIndex: index, amount: toNano("0.05"), commonContentUrl: file, }; const nftItem = new NftItem(collection); seqno = await nftItem.deploy(wallet, mintParams); console.log(`Successfully deployed ${index + 1} NFT`); await waitSeqno(seqno, wallet); index++; } console.log("Start deploy of new marketplace "); const marketplace = new NftMarketplace(wallet.contract.address); seqno = await marketplace.deploy(wallet); await waitSeqno(seqno, wallet); console.log("Successfully deployed new marketplace"); const nftToSaleAddress = await NftItem.getAddressByIndex(collection.address, 0); const saleData: GetGemsSaleData = { isComplete: false, createdAt: Math.ceil(Date.now() / 1000), marketplaceAddress: marketplace.address, nftAddress: nftToSaleAddress, nftOwnerAddress: null, fullPrice: toNano("10"), marketplaceFeeAddress: wallet.contract.address, marketplaceFee: toNano("1"), royaltyAddress: wallet.contract.address, royaltyAmount: toNano("0.5"), }; const nftSaleContract = new NftSale(saleData); seqno = await nftSaleContract.deploy(wallet); await waitSeqno(seqno, wallet); await NftItem.transfer(wallet, nftToSaleAddress, nftSaleContract.address); } void init();
错误原因
init()是异步函数,内部所有await操作(IPFS上传、钱包初始化、合约部署等)都可能抛出错误,但当前代码通过void init();调用时,没有处理Promise的拒绝状态,一旦任何异步操作失败就会触发未捕获的Promise拒绝错误。
解决方案
方案1:在init()内部添加try/catch捕获错误
修改init函数,用try/catch包裹所有逻辑并输出错误详情:
async function init() { try { // 原有代码全部放入try块内 const metadataFolderPath = "./data/metadata/"; const imagesFolderPath = "./data/images/"; const wallet = await openWallet(process.env.MNEMONIC!.split(" "), true); console.log("Started uploading images to IPFS..."); const imagesIpfsHash = await uploadFolderToIPFS(imagesFolderPath); console.log( `Successfully uploaded the pictures to ipfs: https://gateway.pinata.cloud/ipfs/${imagesIpfsHash}` ); console.log("Started uploading metadata files to IPFS..."); await updateMetadataFiles(metadataFolderPath, imagesIpfsHash); const metadataIpfsHash = await uploadFolderToIPFS(metadataFolderPath); console.log( `Successfully uploaded the metadata to ipfs: https://gateway.pinata.cloud/ipfs/${metadataIpfsHash}` ); console.log("Start deploy of nft collection..."); const collectionData = { ownerAddress: wallet.contract.address, royaltyPercent: 0.05, // 0.05 = 5% royaltyAddress: wallet.contract.address, nextItemIndex: 0, collectionContentUrl: `ipfs://${metadataIpfsHash}/collection.json`, commonContentUrl: `ipfs://${metadataIpfsHash}/`, }; const collection = new NftCollection(collectionData); let seqno = await collection.deploy(wallet); console.log(`Collection deployed: ${collection.address}`); await waitSeqno(seqno, wallet); // Deploy nft items const files = await readdir(metadataFolderPath); files.pop(); let index = 0; seqno = await collection.topUpBalance(wallet, files.length); await waitSeqno(seqno, wallet); console.log(`Balance top-upped`); for (const file of files) { console.log(`Start deploy of ${index + 1} NFT`); const mintParams = { queryId: 0, itemOwnerAddress: wallet.contract.address, itemIndex: index, amount: toNano("0.05"), commonContentUrl: file, }; const nftItem = new NftItem(collection); seqno = await nftItem.deploy(wallet, mintParams); console.log(`Successfully deployed ${index + 1} NFT`); await waitSeqno(seqno, wallet); index++; } console.log("Start deploy of new marketplace "); const marketplace = new NftMarketplace(wallet.contract.address); seqno = await marketplace.deploy(wallet); await waitSeqno(seqno, wallet); console.log("Successfully deployed new marketplace"); const nftToSaleAddress = await NftItem.getAddressByIndex(collection.address, 0); const saleData: GetGemsSaleData = { isComplete: false, createdAt: Math.ceil(Date.now() / 1000), marketplaceAddress: marketplace.address, nftAddress: nftToSaleAddress, nftOwnerAddress: null, fullPrice: toNano("10"), marketplaceFeeAddress: wallet.contract.address, marketplaceFee: toNano("1"), royaltyAddress: wallet.contract.address, royaltyAmount: toNano("0.5"), }; const nftSaleContract = new NftSale(saleData); seqno = await nftSaleContract.deploy(wallet); await waitSeqno(seqno, wallet); await NftItem.transfer(wallet, nftToSaleAddress, nftSaleContract.address); } catch (error) { console.error("执行过程中出现错误:", error); process.exit(1); // 非0退出码标识执行失败 } } init(); // 无需再用void
方案2:在调用init()时添加.catch()处理
保留原有init函数,修改调用方式:
init().catch(error => { console.error("执行过程中出现错误:", error); process.exit(1); });
后续排查
添加错误捕获后,运行yarn start会输出具体错误信息,可根据错误详情进一步定位问题(比如IPFS上传失败可能是网络问题、钱包密钥错误、合约部署参数问题等)。
内容的提问来源于stack exchange,提问作者user24786531
相关产品推荐
相关产品推荐

