我正在尝试创建一个通知应用程序,这是我的代码:
function sendNotification(messageUser, messageText, messageDepartment, messageTopic, userIDs) {
var userAndroid = [];
var userIOS = [];
var userDevice;
console.log(userIDs);
for (var i = 0; i < userIDs.length; i++) {
searchRegisterDevices(userIDs[i], function(result) {
if (result) {
for (var j = 0; j < result.length; j++) {
userDevice = {platform: result[j].platform, token: result[j].token};
if (userDevice.platform == 'android') {
userAndroid.push(userDevice);
} else {
userIOS.push(userDevice);
}
}
} else {
console.log("ERROR");
}
});
}
console.log(userAndroid);
if (userAndroid.length > 0) {
}
&#13;
我的问题是,虽然我是&#34;用于循环&#34;收集我的设备,我的代码继续发送到发送部分并因为userAndroid为空而失败。我可以做些什么来修复这个回调地狱呢?我需要等到我的for循环完成后再继续发送消息。任何帮助将不胜感激!
答案 0 :(得分:0)
这里的问题是您在for循环中执行异步请求,而不处理异步。您正在混合同步for
循环和(可能)异步searchRegisterDevices
。循环变量将继续递增,直到达到极限。因此,当您从事件堆栈中弹出回调函数时,userIDs[i]
的值为userIDs[userIDs.length]
,感谢lexical scoping of javascript variables
您需要做的是这三个中的一个patterns:
var j = 10;
for (var i = 0; i < j; i++) {
(function(cntr) {
// here the value of i was passed into as the argument cntr
// and will be captured in this function closure so each
// iteration of the loop can have it's own value
asychronousProcess(function() {
console.log(cntr);
});
})(i);
}
如果你可以修改asychronousProcess()函数,那么你可以在那里传递值并让asychronousProcess()函数将cntr返回到回调函数,如下所示:
var j = 10;
for (var i = 0; i < j; i++) {
asychronousProcess(i, function(cntr) {
console.log(cntr);
});
}
如果您有一个完全支持ES6的Javascript执行环境,您可以在for循环中使用let,如下所示:
const j = 10;
for (let i = 0; i < j; i++) {
asychronousProcess(function() {
console.log(i);
});
}
当然,asychronousProcess
代表您的searchRegisterDevices
服务电话。
答案 1 :(得分:0)
以下是我将如何使用babel
和更新的JS语法:
import rfpify from 'rfpify';
const findDevice = rfpify(searchRegisteredDevices);
async function sendNotification({message, toUserIDs}) {
let devices = await Promise.all(toUserIDs.map(id=>findDevice(id)));
devices = devices.map( ({platform,token}) => { return {platform,token} } );
const androidUsers = devices.filter(d => d && d.platform == 'android');
const iOSUsers = devices.filter(d => d && d.platform != 'android');
return {message, androidUsers, iOSUsers};
}
设置babel
和rfpify
:npm i -S rfpify; npm i -D babel-cli babel-preset-latest babel-plugin-transform-runtime
。为代码运行创建src
,为lib
运行的输出程序创建node
。把它放在.babelrc中:{ "presets": [ "latest"], "plugins": [["transform-runtime"]] }
在package.json "scripts"
内:"build": "babel src -d lib"
使用npm run build
构建。
注意:这假设您在Node~6.3.1上。您可以使用nvm
来安装/设置节点版本。
您需要花时间确保自己100%熟悉回调,然后学习承诺,然后研究async/await
和babel
的工作原理。要真正习惯这一切需要一些时间。