Javascript 承诺并不像我期望的那样
我使用Express进行路由,使用Sequelize进行数据库管理Javascript 承诺并不像我期望的那样,javascript,ecmascript-6,sequelize.js,es6-promise,Javascript,Ecmascript 6,Sequelize.js,Es6 Promise,我使用Express进行路由,使用Sequelize进行数据库管理 app.get('/api/users/:username', (req, res) => { let username = req.params.username; findChattersPerRole() .then(chattersPerRole => { console.log('instakbot should\'ve been added by now...'); }
app.get('/api/users/:username', (req, res) => {
let username = req.params.username;
findChattersPerRole()
.then(chattersPerRole => {
console.log('instakbot should\'ve been added by now...');
});
});
函数findChattersPerRole返回一个对象,其中每个用户的用户名和角色都是另一个对象
const findChattersPerRole = () => {
return fetch('https://tmi.twitch.tv/group/user/instak/chatters')
.then(parseJSON)
.then(r => {
let chatters = r.chatters;
let chattersPerRole = Object.keys(chatters).map(role => {
return chatters[role].map(username => {
console.log('findOrCreateViewer will be executed after this');
findOrCreateViewer(username, role);
return {
username: username,
role: role
};
});
});
return Promise.resolve(flattenDeep(chattersPerRole));
}).catch(err => {
console.log(`Error in fetch: ${err}`);
});
};
问题是,在我的过程中,我希望console.log('instakbot现在应该已经添加了…')代码>将在查看器插入数据库后执行,因为在函数findChattersPerRole中,我已经使用函数findOrCreateViewer插入了查看器。我预计会发生这种情况,因为在我的路径中,当findChattersPerRole()被解析时,我会编写console.log
const findOrCreateViewer = (username, role) => {
return Viewer.findOrCreate({
where: {
username
},
defaults: {
instakluiten: 5,
role
}
}).spread((unit, created) => {
console.log('unit is: ', unit.dataValues.username);
if(created){
return `created is ${created}`;
}else{
return unit;
}
});
};
然而,在我的终端你可以看到,这不是它发生的方式。。。为什么我的承诺没有在预期的时间执行?
在findOrCreateViewer(用户名、角色)之后返回{username:…}
代码>在调用函数之后和插入任何数据之前立即发生。这也意味着返回Promise.resolve(flattedeep(chattersPerRole))代码>在插入任何数据之前发生,等等
您说过findOrCreateViewer
返回一个承诺,因此您需要等待该承诺得到解决(即,等待数据插入后),然后再继续执行其他操作
您希望chattersPerRole
成为一个承诺数组,并且只有在所有承诺都得到解决后才能继续
这很容易通过承诺实现。所有:
const findChattersPerRole = () => {
return fetch('https://tmi.twitch.tv/group/user/instak/chatters')
.then(parseJSON)
.then(r => {
let chatters = r.chatters;
let chattersPerRole = Object.keys(chatters).map(
role => chatters[role].map(username => {
console.log('findOrCreateViewer will be executed after this');
return findOrCreateViewer(username, role).then(
() => ({username, role})
);
});
);
return Promise.all(flattenDeep(chattersPerRole));
}).catch(err => {
console.log(`Error in fetch: ${err}`);
});
};
现在,findChartersErrorle
返回的承诺将在findOrCreateViewer
返回的所有承诺得到解决后得到解决。findOrCreateViewer(用户名、角色)之后的返回{username:}
代码>在调用函数之后和插入任何数据之前立即发生。这也意味着返回Promise.resolve(flattedeep(chattersPerRole))代码>在插入任何数据之前发生,等等
您说过findOrCreateViewer
返回一个承诺,因此您需要等待该承诺得到解决(即,等待数据插入后),然后再继续执行其他操作
您希望chattersPerRole
成为一个承诺数组,并且只有在所有承诺都得到解决后才能继续
这很容易通过承诺实现。所有:
const findChattersPerRole = () => {
return fetch('https://tmi.twitch.tv/group/user/instak/chatters')
.then(parseJSON)
.then(r => {
let chatters = r.chatters;
let chattersPerRole = Object.keys(chatters).map(
role => chatters[role].map(username => {
console.log('findOrCreateViewer will be executed after this');
return findOrCreateViewer(username, role).then(
() => ({username, role})
);
});
);
return Promise.all(flattenDeep(chattersPerRole));
}).catch(err => {
console.log(`Error in fetch: ${err}`);
});
};
现在,findChattersPerRole
返回的承诺将在findOrCreateViewer
返回的所有承诺得到解决后得到解决。承诺没有任何魔力。返回承诺并不意味着调用函数将被阻塞,而是意味着可以轻松地链接回调以处理结果。你需要使用
function findChattersPerRole() {
return fetch('https://tmi.twitch.tv/group/user/instak/chatters')
.then(parseJSON)
.then(r => {
let chatters = r.chatters;
let chattersPerRole = Object.keys(chatters).map(role => {
return chatters[role].map(username => {
console.log('findOrCreateViewer will be executed after this');
return findOrCreateViewer(username, role).then(() => {
// ^^^^^^ ^^^^^
return {
username: username,
role: role
};
});
});
});
return Promise.all(flattenDeep(chattersPerRole));
// ^^^ get a promise for an array of results from an array of promises
}).catch(err => {
console.log(`Error in fetch: ${err}`);
});
}
承诺没有魔力。返回承诺并不意味着调用函数将被阻塞,而是意味着可以轻松地链接回调以处理结果。你需要使用
function findChattersPerRole() {
return fetch('https://tmi.twitch.tv/group/user/instak/chatters')
.then(parseJSON)
.then(r => {
let chatters = r.chatters;
let chattersPerRole = Object.keys(chatters).map(role => {
return chatters[role].map(username => {
console.log('findOrCreateViewer will be executed after this');
return findOrCreateViewer(username, role).then(() => {
// ^^^^^^ ^^^^^
return {
username: username,
role: role
};
});
});
});
return Promise.all(flattenDeep(chattersPerRole));
// ^^^ get a promise for an array of results from an array of promises
}).catch(err => {
console.log(`Error in fetch: ${err}`);
});
}
findOrCreateViewer
似乎是异步的,所以您希望该函数返回一个承诺,并执行类似于return promise.all(chattersPerRole)的操作代码>其中chattersPerRole
是一个承诺数组(由return findOrCreateViewer(username,role)创建。然后(()=>({username,role}));
来自.map
回调)。因此,我可以说的不是价差。然后(return Promise.resolve(unit));?我不知道.spread
做什么。它是否回报了承诺?如果是,那么您可能不需要更改该函数,但您必须对返回值进行处理(如我的第一条注释所示)。目前您没有对它做任何操作:findOrCreateViewer(用户名、角色)代码>.Yes spread返回一个承诺。哦,你在第一次编辑后就失去了我,我在这个问题上工作了这么久,我的头都痛了。在这种情况下,为什么仅仅调用findOrCreateViewer(…)是一件坏事,或者至少不是最好的决定?因为您没有使用返回的承诺执行任何操作,所以在继续执行其他操作之前,您不知道何时“完成”(即插入数据)。如果您依赖异步操作按顺序运行,则需要等待它们中的每一个都完成,这就是Promissions提供给您的。findOrCreateViewer
似乎是异步的,因此您希望该函数返回Promission并执行类似于return Promission.all(chattersPerRole)的操作代码>其中chattersPerRole
是一个承诺数组(由return findOrCreateViewer(username,role)创建。然后(()=>({username,role}));
来自.map
回调)。因此,我可以说的不是价差。然后(return Promise.resolve(unit));?我不知道.spread
做什么。它是否回报了承诺?如果是,那么您可能不需要更改该函数,但您必须对返回值进行处理(如我的第一条注释所示)。目前您没有对它做任何操作:findOrCreateViewer(用户名、角色)代码>.Yes spread返回一个承诺。哦,你在第一次编辑后就失去了我,我在这个问题上工作了这么久,我的头都痛了。在这种情况下,为什么仅仅调用findOrCreateViewer(…)是一件坏事,或者至少不是最好的决定?因为您没有使用返回的承诺执行任何操作,所以在继续执行其他操作之前,您不知道何时“完成”(即插入数据)。如果您依赖异步操作按顺序运行,那么您需要等待它们中的每一个都完成,这就是承诺给您的。感谢您花时间向我解释这一点,非常感谢。你能解释一下Promise.resolve和Promise.all的区别吗?我现在明白了。一切都是这样,但我想我已经有了。决心,而我显然不是。另外,()=>({username,role})
是否是一种与返回{…}等价的ES6语法?我想是的,但我宁愿确定。谢谢你