大佬们,我使用puppeteer里的方法**$$eval** 去爬一下页面的数据,结果发现引入的nanoid不能使用,刚开始还以为是nanoid不支持commonJS写法导致的,结果调试发现在eval函数外使用可以打印成功,eval里使用就报错了 注意:$$eval返回一个promise async callback(pg) { console.log(nanoid());//这里能打印出来 const imgList = await pg.$$eval('div.swiper-wrapper>div.swiper-slide>div>img', els => els.map((el, index) => { return { imgUrl: el.src, alt: '图片', id: index, imgKey:nanoid()//这里不能使用nanoid } })) || [] return imgList } 报的错误: node:internal/process/promises:279 triggerUncaughtException(err, true /* fromPromise */); ^ Error [ReferenceError]: nanoid is not defined pptr:$$eval;Object.callback%20(D%3A%5C%E9%A1%B9%E7%9B%AE%5C%E7%88%AC%E8%99%AB%E7%B3%BB%E7%BB%9F%5Ccrawler%5Ccrawlers%5Cslider.js%3A8%3A34):6:24 at $$eval ($$eval at Object.callback (D:\项目\爬虫系统\crawler\crawlers\slider.js:8:34), :5:23) at $$eval ($$eval at Object.callback (D:\项目\爬虫系统\crawler\crawlers\slider.js:8:34), :0:12) at ExecutionContext.#evaluate (D:\项目\爬虫系统\crawler\node_modules\puppeteer-core\lib\cjs\puppeteer\common\ExecutionContext.js:254:55) at async ExecutionContext.evaluate (D:\项目\爬虫系统\crawler\node_modules\puppeteer-core\lib\cjs\puppeteer\common\ExecutionContext.js:151:16) at async CDPJSHandle.evaluate (D:\项目\爬虫系统\crawler\node_modules\puppeteer-core\lib\cjs\puppeteer\common\JSHandle.js:48:16) at async Promise.all (index 0) at async CDPElementHandle.$$eval (D:\项目\爬虫系统\crawler\node_modules\puppeteer-core\lib\cjs\puppeteer\api\ElementHandle.js:227:26) at async Object.callback (D:\项目\爬虫系统\crawler\crawlers\slider.js:8:25) at async module.exports (D:\项目\爬虫系统\crawler\libs\crawler.js:10:18) 有大佬知道为什么吗
遇到一个 "TypeScript" 中有关 "Promise" 的类型推导问题: 以下代码中,"resolve" 会有明确的类型限制,但 "reject" 却没有,想知道如何才能做到? type P1 = Promise; const p1: P1 = new Promise((resolve, reject) => { // Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'?ts(2794) resolve(); resolve(1); // Argument of type 'string' is not assignable to parameter of type 'number | PromiseLike'.ts(2345) resolve("str"); reject(); reject(123); reject("str"); }); "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/c/user/20241012/bb39482eb9d6bfabbcc2882170fd5e0a.png) 查看 "Promise" 的类型声明 "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/c/user/20241012/388d99ec4a96cdba11420631d3201307.png) 只有一个泛型参数,貌似不支持。 找到了这篇文章,文章的结论是:无法定义,也无需定义。 "Typescript 中 Promise reject 的类型该如何定义?" (https://link.segmentfault.com/?enc=AJ9XaoGxvrAtYShtThPgpw%3D%3D.ZB4Tu8VkSGlSGuVbLpAVCVLQ2CSKk1st19kHbaMpYSgAK9tNH9hHXniteQW2G4HgnwCd3MChcgUbCxhzA%2FifyE99cIhvkhRqGD10ayFTh0XkTeGK%2BZYLE8mJ6Bn3y0P4) 希望 "reject" 也能有明确的类型推导,但貌似原理上不可行。 那么,在处理 "catch" 的时候,编辑器报出来的 "any",应该怎么处理比较优雅呢? p1.catch((err: any) => {}) 除了在这里直接声明,还有什么最佳实践吗?
遇到一个问题:下面是拿到一个数组返回,通过遍历返回一个值,我之前习惯用map去遍历。 const getCapture=async ()=>{ let result=await ipcRenderer.invoke('goCapture-event') for(const m of result){ if(m.name==='整个屏幕'){ let str=m.thumbnail.crop({x:0,y:0,width:1200,height:1170}) const imgSrc=str.toDataURL() return imgSrc } } /* result.map(m=>{ if(m.name==='整个屏幕'){ console.log(m) let str=m.thumbnail.crop({x:0,y:0,width:1000,height:1000}) const imgStr=str.toDataURL() return imgStr } }) */ } 这是map的遍历: result.map(m=>{ if(m.name==='整个屏幕'){ console.log(m) let str=m.thumbnail.crop({x:0,y:0,width:1000,height:1000}) const imgStr=str.toDataURL() return imgStr } }) 这样返回的竟然是空, 但是如果用for,就可以正确返回: for(const m of result){ if(m.name==='整个屏幕'){ let str=m.thumbnail.crop({x:0,y:0,width:1200,height:1170}) const imgSrc=str.toDataURL() return imgSrc } } js中for和map还有这区别吗?
js Promise 返回数组但无法使用 该如何返回结果呢? let element = document.querySelectorAll('.test') let promise = new Promise((resolve,reject) => { let imgs = [] for (var i = 0; i { console.log(e, e.length) }) 在这里打印e,可以看到是个数组,但e.length显示就是0;而且直接使用e[0]就是undefined
哪些场景下使用await/async更好?哪些场景下使用then更好? 我的认为await/async的出现是为了改善then的使用,当比较复杂的时候,await/async会起到作用,当问题比较简单的时候用then。但是我们还是应该选择其中一种,这样代码风格比较统一。 例如我下面这个需求使用的await/async不知道是否合适(是不是变得麻烦了?) 工作1:获得选择列表,并默认选择全部。 工作2:根据选择的单位和其他信息向服务端发送请求,获取数据之后根据数据刷新页面 当初始加载该页面的时候,整合工作1和工作2。 async function getDwSelections() { try { const result = await getDwList(); if (!result.isSucceed) throw new Error("获取单位列表失败,错误信息:' + result.errMsg") const data = result.data[0].datas console.log("dw selections: ", data); dwSelections.value.push({ value: "全部", label: "全部" }) for (const item of data) { dwSelections.value.push({ value: item.dwdm, label: item.dwmc }) } selectedDw.value = "全部"; } catch (error) { const errorMessage = error instanceof Error ? error.message : error; throw new Error(errorMessage); } } async function query() { try { const result = await getTableData({dwdm: selectedDw.value === "全部" ? '' : selectedDw.value, ny: selectedDate.value}) if (!result.isSucceed) throw new Error("获取数据失败,错误信息:" + result.errMsg) rqToDm.value = {}; const data = result.data[0].datas; const newTableData = new Map(); const newDateFields = new Set(); const currentDate = common.getCurrentDate("yyyy-MM-dd"); for (const entry of data) { if(entry.rqdm > currentDate) continue; if (newTableData.has(entry.jlid)) { newTableData.get(entry.jlid)[entry.rq] = entry.rjql; } else { newTableData.set(entry.jlid, { jlid: entry.jlid, ny: selectedDate.value, dwmc: entry.dwmc, jqd: entry.jqd, dlgs: entry.dlgs, jqfs: entry.jqfs, ljjql: entry.ljjql, rpjql: entry.rpjql, ljdsl: entry.ljdsl, [entry.rq]: entry.rjql }) } newDateFields.add(entry.rq) rqToDm.value[entry.rq] = entry.rqdm; } dateFields.value = Array.from(newDateFields).map(e => { return {"label": e, "prop": e}; }); tableData.value = Array.from(newTableData.values()); } catch (error) { const errorMessage = error instanceof Error ? error.message : error; throw new Error(errorMessage); } } onMounted(async () => { loading.value = true; try { await getDwSelections(); await query() } catch (error) { ElMessage.error(error.message); } loading.value = false; }) 附:代码中有什么其他问题也欢迎指正。
const arr = [1,2,3,4,5,6]; const result = []; const fn = (item) => { let time = Math.ceil(Math.random()*1000) return new Promise(resolve => { setTimeout(() => { resolve(item) }, time); }) } arr.forEach(async (item) => { const val = await fn(item); result.push(val); console.log(result); }) forEach如何实现同步
关于react中useEffect执行顺序,官网文档说useEffect在mouseOver触发的情形下,useEffect会在浏览器绘制最新DOM之后异步执行,但是我试验的情况是在useEffect的alert执行时,最新的DOM还没有在页面上绘制出来,请问这是什么原因?同时还有关于Promise、SetTimeout这类的异步任务,在react的代码执行顺序中是怎么样的呢,希望大佬们可以一并解答下,非常感谢~ 代码如下所示: const Comp: React.FC = () => { const [state, setState] = useState(0); // App Render Log console.log(1); // const flag = Date.now(); // while (Date.now() - flag { console.log('useLayoutEffect'); }, [state]); // useEffect log useEffect(() => { console.log(2); alert('useEffect') }, [state]); // micro callback log Promise.resolve().then(() => console.log(3)); // macro callback log setTimeout(() => { console.log(4) }, 0); return ( setState(n => n + 1)}>点击更新 State {state} ); }; export default Comp; 浏览器初次绘制打印结果是: 1 useLayoutEffect 3 4 2 此时Promise和setTimeout在useEffect之前执行 useEffect是异步执行,符合官网文档解释 onMouseOver时打印结果是: 1 useLayoutEffect 2 3 4 此时Promise和setTimeout却会在useEffect之后执行?? 此时useEffect执行是同步执行,和官网“非点击事件会导致页面DOM先更新再触发useEffect”也相反?? 对于以上我感到很疑惑,希望能帮忙解答下。
Vue Router路由守卫函数beforeEach(to,from,next)里的next方法能否写在Promisse的回调函数than里面?
js 获得了字符串但return 的值是"[object Promise]" const into = async (ids) => { const numbersArray = ids.split('').map(Number) const fetchData = async (number) => { if (number) { const data = await tubeApi.getAnyDevices({ id: number }) return data && data.deviceName ? data.deviceName : '' } return '' } const result = Promise.all(numbersArray.map(fetchData)) return (await result).filter(Boolean) } const intoText = async (ids) => { if (ids) { let getit = await into(ids) console.log(getit.join(',')) return getit.join(',') } } 打印结果没问题 "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/c/user/20240917/1cd1852ef8733dcdc3822ed79a8f537b.png) 看了一些帖子写成现在这样还是一样结果,我承认我对propmise的理解稀碎。。。怎么才能把字符串显示出来呢
const a = (): Promise => { return new Promise((resolve) => { const callback = (mutations: MutationRecord[]) => { // 监听按钮的某个属性变化,此处退出函数 resolve(); }; const observer = new MutationObserver(callback); observer.observe(buttonEl, { attributes: true, }); // 调用一个Promise函数,成功后触发按钮的点击事件,然后监听按钮的属性变化 p().then(() => { buttonEl.click(); }); }); }; const b = async (): Promise => { const callback = (mutations: MutationRecord[]) => { // 监听按钮的某个属性变化,怎么在此处退出函数? }; const observer = new MutationObserver(callback); observer.observe(buttonEl, { attributes: true, }); // 调用一个Promise函数,成功后触发按钮的点击事件,然后监听按钮的属性变化 await p(); buttonEl.click(); }; 如上述示例代码,"a"是常规的Promise写法,现在想要改成"b"那样的async写法,请问该怎么办? 想要这么改的原因是函数内部的逻辑逐渐复杂,会调用多个Promise函数,常规写法会陷入层层嵌套的窘境,不利于维护。