【发布时间】:2022-11-05 06:34:29
【问题描述】:
我在 Electron 和 Node 中有一些异步代码,每个循环在 Jquery 中运行,然后在完成后做出反应:
$(async() => {
if (await window.electronAPI.delete_items(project.name)) {
var _count = 0;
$.each(project.items, function(i, item) {
var promises = item.subitems.map(async function(subitem) {
return await window.electronAPI.update_item(subitem);
});
Promise.all(promises).then(function() {
_count++;
if (_count >= project.items.length) {
$("#overlay").css("display", "none");
console.log("Done");
}
});
});
}
});
但是,所有这些都可以正常工作:
$( "#overlay" ).css( "display", "none" );
立即运行,而:
console.log( "Done" );
更新所有项目后正确运行。
我需要做些什么来防止 JQuery 过早运行?
谢谢 :)
编辑以添加完整代码:
index.js
--------------------------------------
app.whenReady().then( () => {
...
ipcMain.handle( "delete_all_cached_images", delete_all_cached_images );
ipcMain.handle( "update_cached_image", update_cached_image );
/* Create the window */
createWindow();
app.on( "activate", () => {
/* Fix MacOS multi window bug */
if( BrowserWindow.getAllWindows().length === 0 ) createWindow();
} );
} );
async function update_cached_image( e, project_name, image_type, image_size, image_name, image_data ) {
/* Create a new blank image */
let image = new Jimp( image_size, image_size, function ( err, image ) {
if( err )
return false;
/* Map the pixels correct */
var _image_data = Array.from( { length: image_size }, () => Array.from( { length: image_size }, () => undefined ) );
for( var row_sel = 0; row_sel < image_size; row_sel++ )
for( var col_sel = 0; col_sel < image_size; col_sel++ )
_image_data[ col_sel ][ row_sel ] = image_data.data[ row_sel ][ col_sel ];
/* Loop through each pixel to add to the image */
_image_data.forEach( ( row, y ) => {
row.forEach( ( colour, x ) => {
/* If we have a transparent pixel, don't add it to the image */
if( ( colour == "" ) || ( colour == null ) )
image.setPixelColor( Jimp.rgbaToInt( 0, 0, 0, 0 ), parseInt( x ), parseInt( y ) );
else
image.setPixelColor( Jimp.cssColorToHex( "#" + colour ), parseInt( x ), parseInt( y ) );
} );
} );
/* Resize to a nice large size */
image.resize( 512, 512 , Jimp.RESIZE_NEAREST_NEIGHBOR );
/* Save the image to project directory */
image.write( path.join( __dirname, "projects", project_name, "cache", image_type, image_name + ".png" ), ( err ) => {
if( err )
return false;
} );
} );
return true;
}
preload.js
--------------------------------------
const { contextBridge, ipcRenderer } = require( "electron" );
contextBridge.exposeInMainWorld( "electronAPI", {
...
delete_all_cached_images: ( project_name ) => ipcRenderer.invoke( "delete_all_cached_images", project_name ),
update_cached_image: ( project_name, image_type, image_size, image_name, image_data ) => ipcRenderer.invoke( "update_cached_image", project_name, image_type, image_size, image_name, image_data )
} );
renderer.js
--------------------------------------
function update_cached_images() {
$( async () => {
/* First delete all old cached images */
if( await window.electronAPI.delete_all_cached_images( project.name ) ) {
var ti = 0;
Promise.all( project.textures.map( g_texture => {
return Promise.all( g_texture.textures.map( texture => {
return window.electronAPI.update_cached_image( project.name, "textures", 8, ( g_texture.name + "_" + ti++ ), texture );
} ) );
} ) ).then( () => {
$("#overlay").css("display", "none");
console.log("Done");
} ).catch(err => {
console.log(err);
// add something to handle/process errors here
} );
} else {
show_error( "Error caching project textures." );
}
} );
}
【问题讨论】:
-
return await window.electronAPI.update_item(subitem);不应该有await。您想要返回承诺,以便可以将它们放入Promise.all()将等待的数组中。 -
什么跑得太早了?你想让它等什么?在
$.each()中有两个嵌套循环$.each()和.map()。那么,您是否要等待所有循环完成?或者尝试在每次$.each()迭代结束时运行一些东西? -
@jfriend00 是的,没错,它循环遍历项目组,每个项目组也有很多子项目。因此,一旦两个循环都完成,console.log 函数就会完全按预期触发。但是由于某种原因,JQuery 函数会立即触发。
-
@Barmar 即使使用 await,promise* 也会(从外部角度)立即返回,因为该函数是异步的。 (*:实际上是等效的,但这没关系)我错过了什么吗?
-
@GSephElec 你所描述的对我来说没有意义。您是否通过在语句上设置断点来验证它?您还可以在元素上设置 DOM 断点以查看是否有任何内容别的是先修改它。
标签: jquery node.js async-await promise electron