Javascript 如何转换为使用Promises和Q库
我们的应用程序正在增长,我们的客户端脚本需要进行重构,使其更干净、更精简、更易于维护。我尝试使用一个小模块a利用Q库进行承诺链接 如您所见,我需要将一些返回值从初始函数传递回承诺链的其余部分。 有人能帮我理解我需要做什么才能保证第一个函数正常返回吗?然后解释链条 以下是我的出发点:Javascript 如何转换为使用Promises和Q库,javascript,jquery,promise,q,Javascript,Jquery,Promise,Q,我们的应用程序正在增长,我们的客户端脚本需要进行重构,使其更干净、更精简、更易于维护。我尝试使用一个小模块a利用Q库进行承诺链接 如您所见,我需要将一些返回值从初始函数传递回承诺链的其余部分。 有人能帮我理解我需要做什么才能保证第一个函数正常返回吗?然后解释链条 以下是我的出发点: var promise = new Q.Promise(generateMoveRequest) .then(function (id) { var woNum = 12345;
var promise = new Q.Promise(generateMoveRequest)
.then(function (id) {
var woNum = 12345;
return layoutInit(woNum, id, true);
}).then(function (result) {
if (result) {
return moveRequestInit(result, true);
} else {
throw new Error('Template not loaded');
}
}).catch(function (err) {
console.log(err);
});
生成移动请求:
布局初始化:
GenerateMoverRequest函数将执行,但链将不再继续。不,那么执行和布局永远不会被调用
我正在使用Q库,但有些示例似乎忽略了如何启动/创建承诺或将初始函数转换为承诺
有人能解释一下我这里的错误,或者给我一个清晰的例子吗?承诺的jQuery实现不遵循a+标准,所以最好使用Q promise必须接收一个带有两个参数的函数——resolve和reject——它们也是函数——记住Javascript是一种函数语言。成功时必须调用resolve函数,错误时必须调用reject函数。传递给这些函数的任何内容都将在then和catch回调中可用 长话短说,像这样重写代码:
var generateMoveRequest = function (resolve, reject) {
$.ajax({
method: "GET",
url: window.contextPath + '/api/settings/getjson',
data: {name: "the_name"},
success: function (data) {
if (data.length) {
var id = $.parseJSON(data).Parent;
resolve(id);
} else {
reject({message: 'Data not received'})
}
},
error: function (xhr, textStatus, errorThrown) {
reject({message: errorThrown})
}
});
}
var promise = new Q.Promise(generateMoveRequest)
.then(function (id) {
var woNum = 12345;
return layoutInit(woNum, id, true);
}).then(function (result) {
if (result) {
return moveRequestInit(result, true);
} else {
throw new Error('Template not loaded');
}
}).catch(function (error) {
console.log(error.message)
});
稍后编辑-请参阅代码片段以了解承诺的工作原理:
// any number of params
function willPerformAnAsyncOperationAndReturnAPromise(firstParam, secondParam, thirdParam) {
var promise = new Q.Promise(function (resolve, reject) { // always resolve & reject
// perform an async operation, like waiting one second
window.setTimeout(function () {
if (firstParam !== 0) {
// if the 1st param is not 0, it's a success
resolve ({
first: firstParam,
second: secondParam,
third: thirdParam
})
} else {
reject({message: 'The first param must not be null'})
}
}, 1000)
})
return promise
}
willPerformAnAsyncOperationAndReturnAPromise(1, 2, 3)
.then(function (data) {
console.log(data)
})
.catch(function (error) {
console.log(error)
})
willPerformAnAsyncOperationAndReturnAPromise(0, 2, 3)
.then(function (data) {
console.log(data)
})
.catch(function (error) {
console.log(error)
})
一些问题:
您的函数generateMoverRequest应该返回一些东西:$。ajax返回一个承诺,它有一个then方法,所以您可以直接返回它
您不需要创建新的承诺,因为generateMoverRequest会返回一个。这样你就避免了麻烦
建议代码:
generateMoveRequest: function () {
return $.ajax({
method: "GET",
url: window.contextPath + '/api/settings/getjson',
data: {name: "the_name"},
}).then(function (data) {
if (data.length) {
var id = $.parseJSON(data).Parent;
return id;
}
}).catch(function (xhr, textStatus, errorThrown) {
console.log("xhr: ", xhr);
return null;
})
}
var promise = generateMoveRequest()
.then(function (id) {
var woNum = 12345;
return layoutInit(woNum, id, true);
}).then(function (result) {
if (result) {
return moveRequestInit(result, true);
} else {
throw new Error('Template not loaded');
}
}).catch(function (err) {
console.log(err);
});
您的函数GenerateMoverRequest应该返回一些内容:$。ajax返回一个承诺,它有一个then方法,所以您可以直接返回它。@trincot我让它返回一个值=>ID,它是成功回调的返回值,而不是函数GenerateMoverRequest的返回值。谢谢。非常感谢!我现在意识到,任何Promise函数都必须显式地具有resolve和reject。现在更有意义了。在那之后,它就像一个符咒一样工作。它工作了,但它使用了,因为$.ajax已经是一个承诺。请注意,从jQuery 3.0开始,jQuery的承诺实现是。如果我有一个承诺函数,但有两个参数,该怎么办?例如:generateMoverRequestParam1,param2。它是否需要包装到承诺和链?@加密在您的情况下,GenerateMoverRequest是包装在承诺中的异步操作,将始终采用2个参数。我在原始答案中添加了一个解释,以便您更好地理解@如果初始承诺不是A+,则它不是反模式。最好现在就用兼容的类型包装它,因为它以后很容易重构。downvoter可以留下评论让我知道我错过了什么吗?
// any number of params
function willPerformAnAsyncOperationAndReturnAPromise(firstParam, secondParam, thirdParam) {
var promise = new Q.Promise(function (resolve, reject) { // always resolve & reject
// perform an async operation, like waiting one second
window.setTimeout(function () {
if (firstParam !== 0) {
// if the 1st param is not 0, it's a success
resolve ({
first: firstParam,
second: secondParam,
third: thirdParam
})
} else {
reject({message: 'The first param must not be null'})
}
}, 1000)
})
return promise
}
willPerformAnAsyncOperationAndReturnAPromise(1, 2, 3)
.then(function (data) {
console.log(data)
})
.catch(function (error) {
console.log(error)
})
willPerformAnAsyncOperationAndReturnAPromise(0, 2, 3)
.then(function (data) {
console.log(data)
})
.catch(function (error) {
console.log(error)
})
generateMoveRequest: function () {
return $.ajax({
method: "GET",
url: window.contextPath + '/api/settings/getjson',
data: {name: "the_name"},
}).then(function (data) {
if (data.length) {
var id = $.parseJSON(data).Parent;
return id;
}
}).catch(function (xhr, textStatus, errorThrown) {
console.log("xhr: ", xhr);
return null;
})
}
var promise = generateMoveRequest()
.then(function (id) {
var woNum = 12345;
return layoutInit(woNum, id, true);
}).then(function (result) {
if (result) {
return moveRequestInit(result, true);
} else {
throw new Error('Template not loaded');
}
}).catch(function (err) {
console.log(err);
});