gpt4 book ai didi

javascript - 带有 Promise 的同步 Javascript 函数无法正常工作

转载 作者:行者123 更新时间:2023-12-03 01:41:50 25 4
gpt4 key购买 nike

我有以下功能,我希望同步处理这些功能,但不知何故它无法正常工作。

function upload_to_aws(data) {
return new Promise(function(resolve, reject) {
loan_application_id = $('#loan_application_id').val();

var s3BucketName = data.bucket_name;
var s3RegionName = data.region;
AWS.config.update({accessKeyId: data.key, secretAccessKey: data.secret_key, region: s3RegionName});
var s3 = new AWS.S3({params: {Bucket: s3BucketName, Region: s3RegionName}});

aws_url= []
$('.attached_image').each(function() {
if($(this).attr('src') != "/assets/upload_bg.png" && $(this).attr('src') != '' ) {
var timestamp = (new Date()).getTime();
var randomInteger = Math.floor((Math.random() * 1000000) + 1);
filename = 'self_evaluation_images/'+ loan_application_id + '_self_eval_ic_' + timestamp + '.png';
var u = $(this).attr('src').split(',')[1],
binary = atob(u),
array = [];

for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}

var typedArray = new Uint8Array(array);
s3_upload(s3, filename, typedArray).then(function(url_aws) {
aws_url.push(url_aws);
console.log(aws_url)
console.log(aws_url.length)
})
}
})
resolve(aws_url);
})
}

function s3_upload(s3, filename, typedArray) {
return new Promise(function(resolve, reject) {
s3.putObject({Key: filename, ContentType: 'image/png', Body: typedArray.buffer, ContentEncoding: 'base64', ACL: 'public-read'},
function(err, data) {
if (data !== null) {
url_aws = s3.endpoint.href + filename;
resolve(url_aws)
}
else {
reject(err);
}
});
})
}

当调用此函数时,它会调用 upload_to_aws 函数,我希望在它返回 aws_uploaded url 数组之前在该函数中执行所有内容。

$.when(upload_to_aws(data.data)).then(function(aws_uploaded_url) {
console.log(aws_uploaded_url);
})

但目前基本上发生的情况是,在将图像上传到 s3 期间,即使在图像上传到 s3 之前,也会调用 resolve(aws_url) 因此会打印 console.log(aws_uploaded_url) 作为空数组 [] 因为该函数尚未完全执行。

还有其他方法可以处理 JavaScript 中的回调和同步函数吗?

最佳答案

主要问题是代码不会等待 s3_update 返回的 promise 得到解决,并在解析 返回的 promise 之前填充 aws_url 数组upload_to_aws 与该数组(它仍然是空的)。

到目前为止,这是 How do I return the response from an asynchronous call? 中解决的常见问题。 ,但用 s3.putObject 方法代替 AJAX 调用。

您还希望等待多个(零个或多个 promise ),因为请求数量由数据决定。等待多个 Promise 完成涉及使用 Promise.all

Promise.all 调用的实现值是作为参数提供的 Promise 的实现值的数组,按照提供的参数的顺序排列。换句话说,实现的值是帖子中使用的 aws_url 数组。

一种(未经测试的)尝试方法,只需稍作修改即可声明所有变量并简化 s3_upload 可能是:

function upload_to_aws(data) {
var loan_application_id = $('#loan_application_id').val();
var s3BucketName = data.bucket_name;
var s3RegionName = data.region;
AWS.config.update({accessKeyId: data.key, secretAccessKey: data.secret_key, region: s3RegionName});
var s3 = new AWS.S3({params: {Bucket: s3BucketName, Region: s3RegionName}});

var urlPromises = [];
$('.attached_image').each(function() {
if($(this).attr('src') != "/assets/upload_bg.png" && $(this).attr('src') != '' ) {
var timestamp = (new Date()).getTime();
var randomInteger = Math.floor((Math.random() * 1000000) + 1);
var filename = 'self_evaluation_images/'+ loan_application_id + '_self_eval_ic_' + timestamp + '.png';
var u = $(this).attr('src').split(',')[1];
var binary = atob(u);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
var typedArray = new Uint8Array(array);
urlPromises.push( s3_upload(s3, filename, typedArray))
}
});
return Promise.all( urlPromises);
}

function s3_upload(s3, filename, typedArray) { // promisify a call back
return new Promise(function(resolve, reject) {
s3.putObject(
{Key: filename, ContentType: 'image/png', Body: typedArray.buffer, ContentEncoding: 'base64', ACL: 'public-read'},
function(err, data) { err ? reject(err) : resolve( data);}
);
});
}

(如果任何声明的变量应该是全局的,则删除它们前面的 var)。

通过调用 upload_to_aws 返回的 promise 应该通过零个或多个上传网址的数组来实现:

$.when(upload_to_aws(data.data)).then(function(aws_uploaded_urls {
console.log(aws_uploaded_urls);
})

<小时/> JQuery 兼容性(更新)

在版本 3 之前,jQuery 没有实现符合 Aplus promise specificaion 的 promise 。或更高版本的 ECMAScript 版本 6 标准。旧版本的 JQuery 根本无法将 ES6 Promise 识别为 Promise,并且无法等待它们得到解决。

检查您是否使用 JQuery 3 或更高版本以及使用 native Promise 的代码。如果您需要支持 IE 浏览器,您还需要包含支持 Promise.all 的 ES6 风格 Promise 的 Polyfill。

如果您需要支持不再 supported in JQuery 3 的浏览器考虑完全删除 Promise 的使用,并围绕 Deferred 对象的使用重构代码(超出了本答案的范围)。这也将消除在缺乏原生 Promise 支持的旧版浏览器中对 Polyfill 的需求。

如果 .when 方法在使用 ES6 Promise 时出现问题,请考虑使用纯 JavaScript 调用代码:

upload_to_aws(data.data)
.then(function(aws_uploaded_urls) {
console.log(aws_uploaded_urls);
})
.catch( function( err) {
console.log( "upload_to_aws failed: ", err);
}

关于javascript - 带有 Promise 的同步 Javascript 函数无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50809322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com