我们有一个正在发展的应用程序,我们的客户端脚本需要重构为更清洁,更精简,更易于维护。我正在尝试将一个小模块用于使用 Q 库进行保证链接。
正如您所看到的,我需要将一些返回值从初始函数传递回promise链的其余部分。 有人可以帮我理解我需要做些什么才能使第一个函数作为Promise正常返回?然后解释链?
这是我的出发点:
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);
});
生成移动请求:
generateMoveRequest: function () {
$.ajax({
method: "GET",
url: window.contextPath + '/api/settings/getjson',
data: {name: "the_name"},
success: function (data) {
if (data.length) {
var id = $.parseJSON(data).Parent;
return id;
}
},
error: function (xhr, textStatus, errorThrown) {
console.log("xhr: ", xhr);
return null;
}
});
}
布局初始化:
layoutInit: function (num, id, appendLayout) {
$.ajax({
method: "GET",
url: window.contextPath + '/some/url',
data: {num: num, id: id},
success: function (data) {
return layoutInit.callback(data, appendLayout);
},
error: function (xhr, textStatus, errorThrown) {
console.log("xhr: ", xhr);
}
});
},
callback: function (data, appendLayout) {
if (data && data.toString().toLowerCase() !== "blank") {
if (appendLayout) {
$(data).insertBefore($("#detailsection"));
} else {
$("#detailsection").html(data);
}
} else {
$("#detailsection").html('');
}
},
generateMoveRequest 函数将执行,但链永远不会再继续。没有.then()执行和 layoutInit 永远不会被调用。
我正在使用Q库,但有些示例似乎忽略了如何启动/创建承诺或将初始函数转换为Promise。
有人可以解释我在这里遇到的错误或给我一个干净的例子吗?
答案 0 :(得分:1)
承诺的jQuery实现不遵循A +标准,所以你最好用Q.
承诺必须接收带有2个参数的函数 - 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)
});
稍后编辑 - 请参阅片段以了解Promise的工作原理:
// 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)
})
答案 1 :(得分:0)
一些问题:
您的函数var myJSON = Json.stringify(JiraJson);
应该返回一些内容:string jsonString = @"{""fields"":{""customfield_12302"":{""name"":""xyz""}}}";
返回一个承诺(它有一个generateMoveRequest
方法),所以你可以返回它;
您无需创建新承诺,因为$.ajax
会返回一个承诺。这样就可以避免使用promise constructor anti-pattern。
建议代码:
then