在我的JavaScript数据加载承诺中,我需要`setTimeout(resolve)`什么?
我试图探索ES6的承诺,不仅仅是从howto文章中获得简单的示例代码,而是实际尝试将学到的概念实现到代码中,以某种方式在实际项目中有用 下面,我在frontend Vue.js/axios中创建了代码,它成功地使用Promises将数据加载到屏幕的五个区域。在我的后端在我的JavaScript数据加载承诺中,我需要`setTimeout(resolve)`什么?,javascript,vue.js,es6-promise,Javascript,Vue.js,Es6 Promise,我试图探索ES6的承诺,不仅仅是从howto文章中获得简单的示例代码,而是实际尝试将学到的概念实现到代码中,以某种方式在实际项目中有用 下面,我在frontend Vue.js/axios中创建了代码,它成功地使用Promises将数据加载到屏幕的五个区域。在我的后端loadData操作中,我让它人工等待一秒钟,这样我就可以看到屏幕的五个区域中的每一个都以1秒的间隔加载数据: <div id="app" class="pageContent"> <div>Data
loadData
操作中,我让它人工等待一秒钟,这样我就可以看到屏幕的五个区域中的每一个都以1秒的间隔加载数据:
<div id="app" class="pageContent">
<div>Data 1: {{data1}}</div>
<div>Data 2: {{data2}}</div>
<div>Data 3: {{data3}}</div>
<div>Data 4: {{data4}}</div>
<div>Data 5: {{data5}}</div>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
data1: 'loading...',
data2: 'loading...',
data3: 'loading...',
data4: 'loading...',
data5: 'loading...'
},
methods: {
initialize: function () {
const that = this;
this.loadData('data1')
.then(() => {
return that.loadData('data2');
})
.then(() => {
return that.loadData('data3');
})
.then(() => {
return that.loadData('data4');
})
.then(() => {
return that.loadData('data5');
});
},
loadData: function (idCode) {
return new Promise((resolve, reject) => {
const that = this;
axios({
method: 'post',
url: 'controllerShowcaseLoadDataWithPromises',
data: {
action: 'loadData',
idCode: idCode
}
}).then(function (responseObject) {
const response = qsys.getResponse(responseObject);
that[idCode] = response.data.message;
setTimeout(resolve);
});
});
},
}
});
app.initialize();
数据1:{{data1}}
数据2:{{data2}}
数据3:{{data3}}
数据4:{{data4}}
数据5:{{data5}}
const app=新的Vue({
el:“#应用程序”,
数据:{
数据1:'正在加载…',
数据2:'正在加载…',
数据3:'正在加载…',
数据4:'正在加载…',
数据5:'正在加载…'
},
方法:{
初始化:函数(){
常数=this;
this.loadData('data1'))
.然后(()=>{
返回.loadData('data2');
})
.然后(()=>{
返回.loadData('data3');
})
.然后(()=>{
返回.loadData('data4');
})
.然后(()=>{
返回.loadData('data5');
});
},
loadData:函数(idCode){
返回新承诺((解决、拒绝)=>{
常数=this;
axios({
方法:“post”,
url:“ControllerShowCaseLoadDataWithPromissions”,
数据:{
操作:“loadData”,
idCode:idCode
}
}).then(函数(响应对象){
const response=qsys.getResponse(responseObject);
[idCode]=response.data.message;
设置超时(解析);
});
});
},
}
});
app.initialize();
虽然这似乎很好,但有人能解释为什么我必须使用
setTimeout(resolve)
(没有它,代码只执行一次)以及这里到底发生了什么吗?我知道这是执行回调的基本方法,就像我们在承诺之前做的那样,但是什么是更干净、更标准的方法呢?现在做的“更干净”的方法是将所有承诺添加到数组中,并使用承诺。所有:
const requests = [
that.loadData('data1'),
that.loadData('data2'),
that.loadData('data3'),
that.loadData('data4'),
that.loadData('data5')
];
Promise.all(requests).then(value => {
// All resolved values in order
}).catch(error => {
// Error
});
当您不解析承诺时,loadData
函数只执行一次的原因正是因为您没有解析承诺<代码>则
永远不会在链中执行
无需在setTimeout
中包装resolve
…为什么我必须使用setTimeout(resolve)
您不必使用设置超时
,但必须调用解析
(或拒绝
)来解决承诺
这到底是怎么回事
您正在执行一系列异步调用,等待前一个调用完成后再执行下一个调用,因为您将承诺链接在一起的方式。这就是为什么如果您不解析第一个操作,其他操作都不会运行:您已经链接了您的操作,因此在每种情况下,只有在上一个操作成功完成时,下一个操作才会运行。如果您不调用resolve
,尽管操作已完成,但您永远不会解决您创建的承诺,让代码使用该承诺完成操作
我知道这是执行回调的基本方法,就像我们在承诺之前所做的那样,但是什么是更干净、更标准的方法呢
如果必须显式创建承诺,则调用resolve
是标准方法但是,在这种情况下,您不必这样做,因为您已经得到了axios
的承诺。因此loadData
应该是:
loadData: function(idCode) {
return axios({
method: 'post',
url: 'controllerShowcaseLoadDataWithPromises',
data: {
action: 'loadData',
idCode: idCode
}
}).then(function (responseObject) {
const response = qsys.getResponse(responseObject);
this[idCode] = response.data.message;
});
},
请注意,它返回调用的结果,然后从axios
对promise进行调用。(还请注意,由于您使用的是箭头函数,因此不需要=此
对象的。箭头函数将关闭此
)
如果您希望一个接一个地完成操作,那么您的承诺链就是如何做到这一点的,尽管如果您愿意,您可以更简洁地编写它,并且您应该处理错误(同样,不需要that=this
):
如果您希望这五个操作并行(重叠)完成,可以立即启动它们并使用Promise.all
等待它们全部完成:
Promise.all([
this.loadData('data1'),
this.loadData('data2'),
this.loadData('data3'),
this.loadData('data4'),
this.loadData('data5'),
])
.catch(error => {
// handle/report error here
});
最后,根据您的目标浏览器和是否要传输,您还可以使用async
函数和wait
:
loadData: async function(idCode) {
const responseObject = await axios({
method: 'post',
url: 'controllerShowcaseLoadDataWithPromises',
data: {
action: 'loadData',
idCode: idCode
}
});
const response = qsys.getResponse(responseObject);
this[idCode] = response.data.message;
},
在setTimeout(resolve)
之前,有哪些替代方法可以让它工作?使用一个虚拟的axios,我看不出立即调用resolve
有任何问题-所有div都会按顺序填充,无论我是使用resolve()
还是setTimeout(resolve)
?除非您的备选方案根本不调用resolve
,在这种情况下问题很明显,否则在使用Promise构造函数进行其构造的Promise to resolve时,您必须调用resolve
,否则它将永远挂起这里的两个坏习惯:axios
返回一个Promise
,而您正在用自己的Promise
包装承诺,没有任何好的理由。使用函数
而不是箭头函数
会使y
loadData: async function(idCode) {
const responseObject = await axios({
method: 'post',
url: 'controllerShowcaseLoadDataWithPromises',
data: {
action: 'loadData',
idCode: idCode
}
});
const response = qsys.getResponse(responseObject);
this[idCode] = response.data.message;
},