如何转换为使用 Promises 和 Q 库
How to convert to using Promises and Q Library
我们有一个正在增长的应用程序,我们的客户端脚本需要重构,以使其更干净、更精简和更易于维护。我正在尝试使用一个小模块,利用 Q 库进行承诺链接。
如您所见,我需要将一些 return 值从初始函数传回 promise 链的其余部分。
有人可以帮助我理解我需要做些什么才能将第一个函数 return 正确地作为 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 库,但一些示例似乎遗漏了如何 start/create 承诺或将初始函数转换为承诺。
谁能解释一下我这里的错误或提供一个干净的例子?
jQuery promises 的实现不遵循 A+ 标准,所以你最好使用 Q。
promise 必须接收一个带有 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)
})
一些问题:
你的函数 generateMoveRequest
应该 return 一些东西:$.ajax
return 是一个承诺(它有一个 then
方法),所以你可以 return 那;
您不需要像 generateMoveRequest
return 那样创建新的承诺。这样你就可以避免 promise constructor anti-pattern.
建议代码:
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);
});
我们有一个正在增长的应用程序,我们的客户端脚本需要重构,以使其更干净、更精简和更易于维护。我正在尝试使用一个小模块,利用 Q 库进行承诺链接。
如您所见,我需要将一些 return 值从初始函数传回 promise 链的其余部分。 有人可以帮助我理解我需要做些什么才能将第一个函数 return 正确地作为 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 库,但一些示例似乎遗漏了如何 start/create 承诺或将初始函数转换为承诺。
谁能解释一下我这里的错误或提供一个干净的例子?
jQuery promises 的实现不遵循 A+ 标准,所以你最好使用 Q。
promise 必须接收一个带有 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)
})
一些问题:
你的函数
generateMoveRequest
应该 return 一些东西:$.ajax
return 是一个承诺(它有一个then
方法),所以你可以 return 那;您不需要像
generateMoveRequest
return 那样创建新的承诺。这样你就可以避免 promise constructor anti-pattern.
建议代码:
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);
});